0

I have the following Windows Batch File that I have found to greet the user with Good Morning or Good Evening depending on the time of day:

for /f "delims=:" %%A in ("%time%") do if %%A LSS 12 (echo. Good Morning %username%.) else (echo. Good Afternoon %username%.)

However, I would like it to respond based on the following rules:

If the time is 06:00 to 11:59 the greeting should be "Good Morning %username%"

If the time is 12:00 to 17:59 the greeting should be "Good Afternoon %username%"

If the time is 18:00 to 19:59 the greeting should be "Good Evening %username%"

If the time is 20:00 to 05:59 the greeting should be "Shouldn't you be in bed %username%?"

Could some one please advise if this is possible and if so let me know how?

Many thanks,

Bri

Bri
  • 59
  • 6

2 Answers2

3

No need to employ a for loop to dissect %time%. Just take advantage of how string comparisons are done:

@echo off
for /f "tokens=2 delims==" %%I in ('wmic os get localdatetime /format:list') do set "tim=%%I"
set "tim=%tim:~8,4%"
if "%tim%" geq "20" echo Shouldn't you be in bed %username%?&goto :done
if "%tim%" geq "18" echo Good Evening %username%&goto :done
if "%tim%" geq "12" echo Good Afternoon %username%&goto :done
if "%tim%" geq "06" echo Good Morning %username%&goto :done
echo Shouldn't you be in bed %username%
:done

(just to note: if "%time%" geq "1730" ... works too)

Edited in reaction to your comments.

  • implemented a method to get the time independent of locale settings (in ISO format, which is much better to handle than AM/PM format)
  • Q: "what the extra echo Shouldn't you be in bed %username% after the if statements is for? - A: to handle times between midnight (00:00) and 05:59. Logically it would be if "tim" geq "00" ... but that's obsolete.
  • Q: "why do you set up the tim variable using set "tim=%time: =0%"? - A: don't mess with the %time% variable. Setting it disables it's ability to show the actual time, so we just use another variable name. The set command replaces each space in the string with a zero (obsolete when using wmic to get the time)
  • using a AM/PM in programming is just awkward. Converting a 24h time format to a 12AM/PM format for use in code is pure nonsense (from my (European) background it doesn't even make sense for "human readability", but ymmv, when you are used to AM/PM)
Stephan
  • 53,940
  • 10
  • 58
  • 91
  • 1
    @Gerhard: good point. Changed. (whether `%time%` returns a leading space or a leading zero depends on locale settings) – Stephan Nov 22 '21 at 07:37
  • Nice one! I am not sure what the extra ```echo Shouldn't you be in bed %username%``` after the *if* statements is for though. Could you explain? I also noticed you have ```if "%tim%" geq "12" echo Good Morning %username%``` as **Good Morning** when it should be **Good Afternoon**. Also, why do you set up the ```tim``` variable using ```set "tim=%time: =0%"```? – Bri Nov 22 '21 at 11:16
  • @Gerry I see but if all the times are covered by the ```if``` statements then the final option would never be invoked would it? Also, as per my previous comment, why do you set up the ```tim``` variable using ```set "tim=%time: =0%"```? – Bri Nov 22 '21 at 11:45
  • To answer your question on `%tiime:=0%`. depending on your locale settings, hours from 1am to 9 am will be displayed as `h:mm` This space is then replaced by `0` if it exists. Stephan simply created a single variable that will replace any whitespace character with a `0` which will effectively make it then `hh:mm` i.e `07:50` instead of ` – Gerhard Nov 22 '21 at 13:35
  • Thank you for the explanation and thank you both for your help. – Bri Nov 22 '21 at 15:07
  • @Bri, no problem, please remember to mark the answer as correct, if you feel it solved your problem. – Gerhard Nov 22 '21 at 15:20
  • Guys, I tested this earlier today and it correctly gave both good morning and good afternoon output but I have just ran it now (4:52PM here GMT) and I got Shouldn't you be in bed. Can someone please confirm that I am reading the code correctly - IE 06:00am - 11:59am = Good Morning, 12:00pm - 06:00pm = Good Afternoon, 06:01pm - 07:59pm =Good Evening and finally 08:00pm - 05:59am = Shouldn't you be in bed? – Bri Nov 22 '21 at 16:56
  • What's the format of your `%time%` variable? Do you have "American" format 12h - AM/PM or "European" format (also known as "Military") 24h? To make the script independent of local settings, you should use [another way to get the time string](https://stackoverflow.com/questions/7727114/batch-command-date-and-time-in-file-name/18024049#18024049) – Stephan Nov 22 '21 at 19:33
  • Thanks @Stephen. Using your answer in the other thread I think I have sorted this. Please check my revised answer. I'd appreciate any comments you may have and/or code changes. – Bri Nov 25 '21 at 09:34
0

For clarity, below is the fully working solution I used.

NOTE: I am using 24 hour time for the greeting but also converting the time to a 12 hour format and adding AM/PM for displaying the time.

@echo off &cls
mode con: cols=100 lines=40  &color f0
setLocal

REM Get current system date and time
for /f "tokens=2 delims==" %%I in ('wmic os get localdatetime /format:list') do set currdatetime=%%I
echo. %currdatetime%
echo. YYYYMMDDhhmmss.(milliseconds)(always 000)+/-(minutes difference to UTC) &echo.

REM Get individual variables for date from %currdatetime%
set _day=%currdatetime:~6,2%
set _month=%currdatetime:~4,2%
set _year=%currdatetime:~-0,4%

REM Display examples
echo. Day: %_day%, Month: %_month% and Year: %_year%
echo.
echo. USA Date: %_month%/%_day%/%_year% (mm-dd-yyyy)
echo. ENG Date: %_day%/%_month%/%_year% (dd-mm-yyyy)
echo.

REM Get individual variables for time from %currdatetime%
set _24hour=%currdatetime:~8,2%
set _min=%currdatetime:~10,2%
set _sec=%currdatetime:~12,2%

REM Display examples
echo.
echo. 24 hour time: %_24hour%:%_min%
echo. Hour: %_24hour%, Min: %_min% and Sec: %_sec%
echo.

REM Convert to 12 hour format
for /F "tokens=1,2,3 delims=:,. " %%A in ('echo %_24time%') do ( set /a "_12hour=100%%A%%100")

REM Add AM/PM
if %_12hour% geq 12 (
set _ampm=PM
set /a "_12hour-=12"
) else set "_ampm=AM"
if %_12hour% equ 0 set "_12hour=12"
if %_12hour% lss 10 set "_12hour=0%_12hour%"

REM Display examples
echo.
echo. 12 hour time: %_12hour%:%_min%%_ampm%
echo. Hour: %_12hour%, Min: %_min% and Sec: %_sec%
echo.

REM Greet user differently depending on the time
if "%_24hour%" geq "20" echo. It's %_12hour%:%_min%%_ampm%^! Bit late to be working isn't it %username%? &goto :done
if "%_24hour%" geq "18" echo. Good Evening %username%, the time is %_12hour%:%_min%%_ampm%. &goto :done
if "%_24hour%" geq "12" echo. Good Afternoon %username%, the time is %_12hour%:%_min%%_ampm%. &goto :done
if "%_24hour%" geq "06" echo. Good Morning %username%, the time is %_12hour%:%_min%%_ampm%. &goto :done
echo. It's %_12hour%:%_min%%_ampm%^! Bit late to be working isn't it %username%?
:done

endlocal
echo. Press any key to exit &>nul timeout /t -1 &exit /B
Bri
  • 59
  • 6
  • this doesn't work. At 08:12 (in the morning), you'll get ` Good Evening Steph, the time is 08:12AM.` due to the way, `if` does string comparison ("08:12AM" is actually GEQ "06:00pm"`) (that's why AM/PM format is bad in programs). – Stephan Nov 23 '21 at 18:07
  • I see. However, the time format needs to be 12 hour for the rest of my batch file so is there a way I can have it like ```if "%time%" geq "06:00am" or lss "12:00pm" echo. Good Morning %username%, the time is %time%. &goto :done```? I'd then repeat this for each time slot. – Bri Nov 24 '21 at 13:17
  • No. `08:23AM` is greater than `08:13PM`(`0`, `8`, and `:` is the same, `2` is greater than `1`, the rest isn't even processed after the first mismatch). Unlike "real" programming languages, batch has no concept of date or time. It's only variable type is STRING (even `set /a` gets strings as input, converts them to integer "on the fly" to do the math, and outputs a string). You could trick it with putting AM/PM in front of the numbers, but why bother if you have the time in ISO format. – Stephan Nov 24 '21 at 14:31
  • Makes sense now you've explained it. So what do you suggest to accomplish this? – Bri Nov 24 '21 at 15:12
  • I suggest using a comparable 24h format like in my answer (and additionally convert to AM/PM format for display, when needed). I strongly suggest, *not* to use `%time%`, if you want your script to run on other computers, or even on your own computer in the future. See my answer for a solution to get the time independent of locale settings. – Stephan Nov 24 '21 at 15:51
  • Having looked at the post you linked I have seperated out the time and date in to their own variables, namely **_date** and **_24time**. However, I have no idea how to get a 12 hour time with AM/PM from this. ```for /f "tokens=2 delims==" %%I in ('wmic os get localdatetime /format:list') do set datetime=%%I``` Please help. – Bri Nov 24 '21 at 16:46
  • look at the `tim` variable. It contains the time as `hhmm` You can extract `hh` and `mm` separately with the same method. The two numbers after the colon are the startposition (zerobased!) and length of the extracted string. See `set /?`. – Stephan Nov 24 '21 at 17:00
  • I have the hour, min, and seconds as variables but the hour is 24 hour. The other thread has: ```set "hour=%currtime:~,2%" if "%currtime:~-2%" == "PM" if %hour% lss 12 set /A "hour+=12" if "%currtime:~-2%" == "AM" if %hour% equ 12 set /A "hour-=12" set "hour=0%hour%""``` but I see nowhere that this is used to display a 12 hour time with AM and PM. – Bri Nov 24 '21 at 17:12
  • `set` doesn't display. You need to `echo` your variables to show them to the user. – Stephan Nov 24 '21 at 17:38
  • Yes I know - currently I have ```set _hour=%hour:~-2% &set _min=%currtime:~3,2% &set _sec=%currtime:~6,2% echo Hour: %_hour%, Min: %_min% and Sec: %_sec%``` This allows me to show **Hour: 19**, **Min: 47** and **Sec: 30** which then allows something like this ```set _24time=%_hour%:%_min% &echo 24 hour time: %_24time%``` or **19:47**. What I need to know is how to do the following: ```echo 12 hour time: %_12time%``` or **07:47PM**. – Bri Nov 24 '21 at 19:50
  • What about the code in your answer? Except that you really shouldn't set `time`, it seems to work. – Stephan Nov 24 '21 at 21:23
  • ok I think I've got it. Could you please take a look at the revised answer and offer any suggestions? – Bri Nov 25 '21 at 09:16