Greet according to the time of day

8

3

Challenge

Write a program that greets a user depending on what time of day (GMT) it is.


Output

A string (printed or returned) according to these rules:

  • If the time is 06:00 to 11:59 the greeting has to be "Good morning"
  • If the time is 12:00 to 17:59 the greeting has to be "Good afternoon"
  • If the time is 18:00 to 19:59 the greeting has to be "Good evening"
  • If the time is 20:00 to 05:59 the greeting has to be "Zzz"


Clarifications

  • There is no input
  • The times and greetings must be exactly as shown
  • The time zone is +0 GMT

Examples

Time: 14:45 -> Good afternoon

Time: 05:59 -> Zzz

Time: 9:23 -> Good morning

Time: 18:00 -> Good evening

lolad

Posted 2018-08-08T12:51:44.173

Reputation: 754

1Without a testing environment in which one can manipulate the current time, how would you test this? Wouldn't it be better for the code to receive the current time as input instead? – Skidsdev – 2018-08-08T12:57:34.540

2If not taking input should we be using UTC / local timezone according to some OS spec / whatever we want (needs some restriction though as it's always morning somewhere in the world) – Jonathan Allan – 2018-08-08T13:04:04.737

I think you forgot about Good night... – mbomb007 – 2018-08-08T13:55:05.260

1@mbomb007 the program is sleeping at night – lolad – 2018-08-08T14:19:44.780

2Well, there goes my Novell login script solution - its %GREETING_TIME variable doesn't have "Zzz", it just switches from "evening" to "morning" at midnight. – Neil – 2018-08-08T15:34:56.820

9I recommend against restricting to a specific time zone, but am in favor of restricting to your own system time instead. Many answers are currently invalid because of it. – Erik the Outgolfer – 2018-08-08T18:16:05.670

Answers

12

JavaScript (ES6), 87 bytes

As noticed by TFeld, my original formula was overcomplicated. We can just do:

_=>['Zzz','Good morning','Good afternoon','Good evening'][new Date().getHours()%20/6|0]

Try it online!

Or test this version that takes the hour as parameter.


JavaScript (ES6), 90 bytes

_=>['Zzz','Good morning','Good afternoon','Good evening'][new Date().getHours()*7%20%7>>1]

Try it online!

Or test this version that takes the hour as parameter.

Formula

Given the current hour \$h\$, we find the appropriate greeting index \$i\$ with:

$$i=\left\lfloor\frac{((7\times h) \bmod 20) \bmod 7}{2}\right\rfloor$$

A good thing about this formula is that it does not require any parenthesis once converted to JS:

h * 7 % 20 % 7 >> 1

Table

 Hour |  *7 | mod 20 | mod 7 | >> 1
------+-----+--------+-------+------
   0  |   0 |    0   |   0   |   0
   1  |   7 |    7   |   0   |   0
   2  |  14 |   14   |   0   |   0
   3  |  21 |    1   |   1   |   0
   4  |  28 |    8   |   1   |   0
   5  |  35 |   15   |   1   |   0
   6  |  42 |    2   |   2   |   1
   7  |  49 |    9   |   2   |   1
   8  |  56 |   16   |   2   |   1
   9  |  63 |    3   |   3   |   1
  10  |  70 |   10   |   3   |   1
  11  |  77 |   17   |   3   |   1
  12  |  84 |    4   |   4   |   2
  13  |  91 |   11   |   4   |   2
  14  |  98 |   18   |   4   |   2
  15  | 105 |    5   |   5   |   2
  16  | 112 |   12   |   5   |   2
  17  | 119 |   19   |   5   |   2
  18  | 126 |    6   |   6   |   3
  19  | 133 |   13   |   6   |   3
  20  | 140 |    0   |   0   |   0
  21  | 147 |    7   |   0   |   0
  22  | 154 |   14   |   0   |   0
  23  | 161 |    1   |   1   |   0

Arnauld

Posted 2018-08-08T12:51:44.173

Reputation: 111 334

6

Python 2, 120 106 102 bytes

import time
print['Zzz','Good morning','Good afternoon','Good evening'][int(time.time()/3600%24%20/6)]

Try it online!

Testable here: Try it online!


Similar to Arnauld's answer, but slightly different:

h  %20 /6
---------
0   0   0
1   1   0
2   2   0
3   3   0
4   4   0
5   5   0
6   6   1
7   7   1
8   8   1
9   9   1
10  10  1
11  11  1
12  12  2
13  13  2
14  14  2
15  15  2
16  16  2
17  17  2
18  18  3
19  19  3
20  0   0
21  1   0
22  2   0
23  3   0

Saved:

  • -3 bytes, thanks to Arnauld
  • -1 byte, thanks to N. P.

TFeld

Posted 2018-08-08T12:51:44.173

Reputation: 19 246

3I think you can do /3600%24%20/6. – Arnauld – 2018-08-08T15:03:36.460

2I think you can save a byte by importing time and using time.time() as well – N. P. – 2018-08-08T18:55:23.440

@Arnauld Thanks :) – TFeld – 2018-08-09T06:49:23.793

@JonathanAllan Doesn't work unfortunately. It's still a float – TFeld – 2018-08-09T06:49:41.890

Oh my mistake, you need to index with it :( – Jonathan Allan – 2018-08-09T06:59:34.523

4

R, 97 95 93 Bytes

Using methods found above in R

c("Zzz","Good morning","Good afternoon","Good evening")[as.POSIXlt(Sys.time(),"G")$h%%20/6+1]

Explanation:

c("Zzz","Good morning","Good afternoon","Good evening")      # Creates a vector with the greetings
[                                                            # Open bracket. The number in the bracket will extract the corresponding greeting from the vector below
as.POSIXlt(                                                  # as.POSIXlt converts the object to one of the two classes used to represent date/times
Sys.time(),                                                  # Retrieves the current time on the OS
"G")                                                         # Converts the time to the desired time zone. Does output a warning, but still converts properly to GMT
$h                                                           # Extracts the hour from the object created by as.POSIXlt
%%20/6                                                       # Methodology as used by other golfers
+1]                                                          # Vectors in R start from 1, and not 0 like in other languages, so adding 1 to the value ensures values range from 1 to 4, not 0 to 3

Example

Notice how this line of code, without adding 1, is short 10 elements

c('Zzz','Good morning','Good afternoon','Good evening')[0:23%%20/6]

[1] "Zzz"            "Zzz"            "Zzz"            "Zzz"            "Zzz"            "Zzz"           
[7] "Good morning"   "Good morning"   "Good morning"   "Good morning"   "Good morning"   "Good morning"  
[13] "Good afternoon" "Good afternoon"

Adding 1 ensures that the result obtained is greater than 0

c('Zzz','Good morning','Good afternoon','Good evening')[as.integer(0:23)%%20/6+1]

[1] "Zzz"            "Zzz"            "Zzz"            "Zzz"            "Zzz"            "Zzz"           
[7] "Good morning"   "Good morning"   "Good morning"   "Good morning"   "Good morning"   "Good morning"  
[13] "Good afternoon" "Good afternoon" "Good afternoon" "Good afternoon" "Good afternoon" "Good afternoon"
[19] "Good evening"   "Good evening"   "Zzz"            "Zzz"            "Zzz"            "Zzz"

Sumner18

Posted 2018-08-08T12:51:44.173

Reputation: 1 334

1

Welcome to PPCG! I think you can just divide by 6 regularly to save 2 bytes. You may need to turn it into a function as well, something like this: Try it online!.

– BLT – 2018-08-08T23:03:56.743

@BLT Thank You. When I tested the code in pieces / was yielding floating point numbers, which I didn't think would work in the brackets, thus I used %/% for floor division. I learned something new today. As for turning it into a function, Sys.time() automatically retrieves the current time on any given computer, itself being the sole input in the equation. – Sumner18 – 2018-08-08T23:22:20.373

2It seems like we can use timezone "G" and it'll autocomplete to "GMT". It gives a warning but outputs GMT on my UK-based Windows 10 machine, though it may be region/platform specific? I don't see anything about it in the docs. Saves 2 bytes if we can use it though. – CriminallyVulgar – 2018-08-08T23:42:16.480

@CriminallyVulgar That works here on my US-based Windows 10 machine. Thanks! – Sumner18 – 2018-08-09T17:01:29.800

3

T-SQL, 153 bytes

SELECT CASE WHEN a>18THEN'Good afternoon'WHEN a>12THEN'Good morning'WHEN a>2THEN'Zzz'ELSE'Good evening'END
FROM(SELECT(DATEPART(hh,GETUTCDATE())+6)%24a)a

Try the SQL Fiddle

Explanation:

SELECT
  CASE WHEN a>18 THEN'Good afternoon' --CASE returns the first value in order whose condition is met
       WHEN a>12 THEN'Good morning'
       WHEN a>2  THEN'Zzz'
       ELSE 'Good evening'
       END
FROM( SELECT (      --Use a subquery to treat the time like a 1x1 table - shorter than declaring a variable
    DATEPART(hh,    --Returns the hour part (hh) of the date
      GETUTCDATE()) --Returns current UTC time (as far as the SQL Server is concerned)
        +6)%24      --Virtual time zone where no period crosses midnight, so everything is ordered
        a)          --Give column a 1-letter alias
        a           --Give subquery an alias so SQL Server doesn't complain

Shmeeku

Posted 2018-08-08T12:51:44.173

Reputation: 131

2

Perl 5, 77 bytes

$_=(gmtime)[2]%20;say$_<6?Zzz:"Good ".($_<12?morning:$_<18?afternoon:evening)

Try it online!

Dom Hastings

Posted 2018-08-08T12:51:44.173

Reputation: 16 415

2

Excel, 97 bytes

=VLOOKUP(Hour(Now()),{0,"Zzz";6,"Good morning";12,"Good afternoon";18,"Good evening";20,"Zzz"},2)

Start with the list of cases

0 <= HOUR < 6 : "Zzz"
6 <= HOUR < 12 : "Good morning"
12 <= HOUR < 18 : "Good afternoon"
18 <= HOUR < 20 : "Good evening"
20 <= HOUR : "Zzz"

Then just use a Range-based Vlookup (default if you ommit the 4th argument) with an Array of values:

H= 0 | "Zzz"
H= 6 | "Good morning"
H=12 | "Good afternoon"
H=18 | "Good evening"
H=20 | "Zzz"

{0,"Zzz"; 6,"Good morning"; 12,"Good afternoon"; 18, "Good evening"; 20,"Zzz"}

I experimented with using MOD(HOUR(NOW())+18,24 to shift the hour back by 6 and reduce the cases by 1, but that resulted in 99 bytes. :(

Chronocidal

Posted 2018-08-08T12:51:44.173

Reputation: 571

2

05AB1E, 36 bytes

”‚¿”…•´¯âžÖ#1ú«…Zzz¸«ža•1Ý;`{ùí4²•èè

Try it online!


”‚¿”                                 # Push 'Good'
    …•´¯âžÖ                          # Push 'morning afternoon evening'
           #                         # Split on spaces.
            1ú                       # Pad each with 1 space.
              «                      # Concat good onto it: ['Good morning',...,'Good evening']
               …Zzz¸«                # Concat 'Zzz' onto it.
                     ža              # Get current hour.
                       •1Ý;`{ùí4²•   # Push 33333000000111111222.
                                  è  # indexes[current_hour]->i[6:00AM]->0
                                   è # phrases[indexes[current_hour]]->p[i[6AM]]->'Good morning'.

Magic Octopus Urn

Posted 2018-08-08T12:51:44.173

Reputation: 19 422

1

Powershell, 82 72 bytes

Port of TFeld's answer

('Zzz','Good morning','Good afternoon','Good evening')[(date).Hour%20/6]

mazzy

Posted 2018-08-08T12:51:44.173

Reputation: 4 832

1

Batch, 178 bytes

@for /f "tokens=3" %%a in ('wmic path Win32_UTCTime') do @set/ag=%%a%%20/6
@for %%a in (Zzz.0 "Good morning.1" "Good afternoon.2" "Good evening.3") do @if %%~xa==.%g% echo %%~na

Uses @TFeld's formula. Locale-dependent version is only 128 bytes:

@set/ag=%time:~,2%%%20/6
@for %%a in (Zzz.0 "Good morning.1" "Good afternoon.2" "Good evening.3") do @if %%~xa==.%g% echo %%~na

Neil

Posted 2018-08-08T12:51:44.173

Reputation: 95 035

1

Common Lisp, 103 bytes

(nth(floor(mod(nth-value 2(get-decoded-time))20)6)'("Zzz""Good morning""Good afternoon""Good evening"))

Ungolfed

(nth (floor (mod (nth-value 2 (get-decoded-time))
                 20)
            6)
     '("Zzz" "Good morning" "Good afternoon" "Good evening"))

Common Lisp mostly ignores whitespace as long as it can unambiguously determine where each sub-expression ends, so much of the golfing here is just removing whitespace. Common Lisp also provides the ability for functions to return multiple values, with all but the first discarded if the caller hasn't explicitly requested the 2nd/3rd/etc return values. This allows functions to return auxiliary data, like the floor function performs floor division, but as a secondary return value returns the remainder. This also allows for functions to avoid the overhead of having to package up their return values in a datastructure if the caller is likely to immediately destructure it again. (get-decoded-time) (really itself a shorthand for (decode-universal-time (get-universal-time))) returns the most values of just about any standard function in common lisp... 9, to be exact. The 3rd return value ((nth-value 2 ...) ) is the current hour in 24 hour time. Then it's just computing the proper index into the list of responses and passing that to nth. I have to use floor here as CL would return a proper fraction if I used / for division.

Try it online!

djeis

Posted 2018-08-08T12:51:44.173

Reputation: 281

1

C# (.NET Core), 177 bytes

using System;namespace a{class b{static void Main(string[] a){Console.WriteLine(new String[]{"Zzz","Good morning","Good afternoon","Good evening"}[DateTime.Now.Hour%20/6|0]);}}}

Try it online!

Alice

Posted 2018-08-08T12:51:44.173

Reputation: 121

139 bytes – Embodiment of Ignorance – 2018-12-28T21:12:21.243

1

Japt, 52 bytes

`Zzz,Good ¶rÍÁ,Good af’rÍ9,Good evÀxg`q, gKd %20/6|0

Try it online!

Bejofo

Posted 2018-08-08T12:51:44.173

Reputation: 31

1

C# (Visual C# Interactive Compiler), 91 bytes

Write("Zzz,Good morning,Good afternoon,Good evening".Split(',')[DateTime.UtcNow.Hour%20/6])

Try it online!

Uses Utc Now to get the UTC time.

If it can be a function instead of a full program:

C# (Visual C# Interactive Compiler), 88 bytes

()=>"Zzz,Good morning,Good afternoon,Good evening".Split(',')[DateTime.UtcNow.Hour%20/6]

Try it online!

Test with all the hours(code stolen shamelessly from Arnauld)

Embodiment of Ignorance

Posted 2018-08-08T12:51:44.173

Reputation: 7 014

This is pretty good! Although you probably should use DateTime.UtcNow to get the correct timezone. – dana – 2018-12-29T01:51:49.720

You could remove the trailing semicolon (;) character though! – dana – 2018-12-29T01:58:44.453

The semicolon totally slipped by me. Thanks! – Embodiment of Ignorance – 2018-12-29T16:20:27.080

0

05AB1E, 45 42 bytes

ža7*20%7%2÷U”‚¿”Xi'•´ëX<i'¯âë'žÖ]ðýX>i…Zzz

(h*7%20%7)//2 ported from @Arnauld's JavaScript (ES6) answer.

Try it online or verify all hours.


Original 45 bytes answer:

žaDV6÷U”‚¿”Xi'•´ëX<i'¯âë'žÖ]ðýX3%>iY2÷9Êi…Zzz

Try it online or verify all hours.

Explanation:

ža                 # Get the current hours
  DV               # Duplicate it, and store it in variable `Y`
    6÷U            # Integer-divide it by 6, and store it in variable `X`
”‚¿”               # String "Good"
    Xi             # If `X` is 1:
      '•´          #  Use string 'morning'
    ëX<i           # Else-if `X` is 2:
        '¯â        #  Use string 'afternoon'
    ë              # Else:
     'žÖ           #  Use string 'evening'
           ]       # Close all if-elses
            ðý     # Join the two string literals with a space
X3%>i              # If `X` modulo-3 is 0:
     Y2÷9Êi        # And if `Y` integer-divided by 2 is not 9:
           …Zzz    #  Output string "Zzz" instead
                   # (Implicit else:
                   #   output top of stack, which is the "Good ...")

See the explanation here to understand why ”‚¿” is "Good"; '•´ is "morning"; '¯â is "afternoon"; and 'žÖ is "evening".

Kevin Cruijssen

Posted 2018-08-08T12:51:44.173

Reputation: 67 575

0

Noether, 106 bytes

"Good "~g{2D~d5>d12<&}{g"morning"+P}d{11>d18<&}{g"afternoon"+P}d{17>d20<&}{g"evening"+P}d{20>d6<&}{"Zzz"P}

Try it online!

The command 2D returns the hour part of the current the time and the rest is a load of if statements.

Beta Decay

Posted 2018-08-08T12:51:44.173

Reputation: 21 478

0

Haskell, 174 bytes

import Data.UnixTime
v h|h<10="Zzz"|1>0="Good "++y h
y h|h<16="morning"|h<22="afternoon"|1>0="evening"
main=do;t<-getUnixTime;print$v$mod(div(read.show.utSeconds$t)3600+4)24

Евгений Новиков

Posted 2018-08-08T12:51:44.173

Reputation: 987

0

C (gcc), 127 bytes

The only really sneaky trick is coercing the hours into unsigned int so that I can force the night values to >14. As the struct tm structure only has integers, I can pretend that it's an array being passed from gmtime_r.

char*s[]={"morning","afternoon","evening"};t,u[9];f(){t=time(0);gmtime_r(&t,u);printf(u[2]-6U>13?"Zzz":"Good %s",s[u[2]/6-1]);}

Try it online!

ErikF

Posted 2018-08-08T12:51:44.173

Reputation: 2 149

Suggest (char*[]){"morning","afternoon","evening"} instead of s – ceilingcat – 2018-09-06T18:38:19.983

0

J, 65 bytes

Another port of TFeld's answer.

('Zzz','Good '&,&>;:'morning afternoon evening'){~<.6%~20|3{6!:0''
  • 3{6!:0'' gets the hour, which is index 3 of the current time vector, from the builtin 6!:0''
  • <.6%~20| is floor of ((hour mod 20) divided by 6)
  • use that as an index {~ into a 4x14 character array containing the greetings.
  • save a few chars by concatenating (,) the string Good to the words morning, afternoon, and evening which are split on whitespace by the J "words" tokenizer (;:). It technically is for tokenizing J sentences, but since J has bare words it ends up splitting on whitespace.

hoosierEE

Posted 2018-08-08T12:51:44.173

Reputation: 760