Working with Time to Categorize as a "Shift"

Hello, new here but Iโ€™m relatively familiar with Excel and Google Sheets. Iโ€™m working on building an app for a company that manages group counseling sessions. Iโ€™ve been able to find a lot of solutions on the forums, YouTube, etc. but Iโ€™m having a lot of difficulty with the time data type and it seems like a lot of other users are as well.

In essence, we have a Start Time and an End Time for groups. Based on the Start Time, I need to designate a โ€œshiftโ€ that the group falls in (i.e. Morning, Midday, Evening). Now, for the frustrating part. Iโ€™ve been able to successfully build this in Excel and Google Sheets but itโ€™s not translating it to AppSheet. Please see below:

Formula that works in Excel and Google Sheets:
-Where cell B2 is the time, i.e. 09:00 AM. Based on this, the sheet would return โ€œMorning (8 AM-Noon)โ€

=IFS(
TIME(HOUR(B2),0,0)<(12/24),โ€œMorning (8 AM-Noon)โ€,
AND(
TIME(HOUR(B2),0,0)>(12/24),TIME(HOUR(B2),0,0)<(16/24)),
โ€œMidday (Noon-4PM)โ€,
AND(
TIME(HOUR(B2),0,0)>(15/24),TIME(HOUR(B2),0,0)<(23/24)),
โ€œEvening (4PM-8PM)โ€)

I thought it would be easy to translate to AppSheet by changing cell B2 to [Start Time], which is my column on AppSheet but itโ€™s not working. Errors is โ€œParameter 1 of function HOUR is of the wrong type.โ€ I think this is because the HOUR() function in AppSheet is designated as a duration and not an actual time value.

I also suspect that this problem is coming up is because AppSheet automatically takes my [Start Time] column and assigns a date (Iโ€™m seeing it as 12/30/1899), so when I try to extract the hour out of the time itโ€™s also automatically giving me a date.

From my reading it also seems that the โ€œTimeโ€ data type includes the date- this doesnโ€™t make any sense to me as we have a โ€œDateโ€ data type already, so โ€œTimeโ€ should stay as time alone.

Iโ€™m really hoping Iโ€™m just missing something here but any help would be greatly appreciated. Iโ€™ve got a few hours at least into trying to set up things related to this one field and the common denominator is dealing with anything related to time.

Thank you,
-Ben

Solved Solved
0 3 1,286
1 ACCEPTED SOLUTION

Steve
Platinum 4
Platinum 4

This suggests the column type is DateTime. If you change the column type to Time, you wonโ€™t have to worry about the unwanted (and potentially problematic) date component.

Hereโ€™s your express reformatted the way I prefer (just aesthetics, not functional):

IFS(
  TIME([Start Time]) < TIME(12:00:00),
    โ€œMorning (8AM-Noon)โ€,
  AND(
    TIME([Start Time]) > TIME(11:59:59),
    TIME([Start Time]) < TIME(16:00:00)
  ),
    โ€œMidday (Noon-4PM)โ€,
  AND(
    TIME([Start Time]) > TIME(15:59:59),
    TIME([Start Time]) < TIME(23:59:59)
  ),
    โ€œEvening (4PM-8PM)โ€,
)

If you change the column type of the Start Time column to Time, you wonโ€™t need to wrap it in TIME():

IFS(
  [Start Time] < TIME(12:00:00),
    โ€œMorning (8AM-Noon)โ€,
  AND(
    [Start Time] > TIME(11:59:59),
    [Start Time] < TIME(16:00:00)
  ),
    โ€œMidday (Noon-4PM)โ€,
  AND(
    [Start Time] > TIME(15:59:59),
    [Start Time] < TIME(23:59:59)
  ),
    โ€œEvening (4PM-8PM)โ€,
)

Wrapping literal times in TIME() is unnecessary, but it is good idea to put literal times in quotes:

IFS(
  [Start Time] < "12:00:00",
    โ€œMorning (8AM-Noon)โ€,
  AND(
    [Start Time] > "11:59:59",
    [Start Time] < "16:00:00"
  ),
    โ€œMidday (Noon-4PM)โ€,
  AND(
    [Start Time] > "15:59:59",
    [Start Time] < "23:59:59"
  ),
    โ€œEvening (4PM-8PM)โ€,
)

The logic in your expression could be simplified as well.

Each condition in an IFS() expression is mutually exclusive and evaluated in order. If the first condition is TRUE, no other conditions are evaluated. Only if the first condition is FALSE is the second condition evaluated.

Your first condition asks, is the start time before 12:00? Your second condition asks, is the start time after 11:59? If the second condition is evaluated, we know the first condition was FALSE, meaning we know the start time is not before 12:00, which is the same as saying it is after 11:59. So asking whether itโ€™s after 11:59 is unneededโ€“we know it is because the first condition was FALSE.

Given that, in the second and third conditions for IFS(), we donโ€™t need to ask the questions already answered by the failure of the previous conditions. This then gives you:

IFS(
  [Start Time] < "12:00:00",
    โ€œMorning (8AM-Noon)โ€,
  [Start Time] < "16:00:00",
    โ€œMidday (Noon-4PM)โ€,
  [Start Time] < "23:59:59",
    โ€œEvening (4PM-8PM)โ€,
)

The last condition asks, is the start time before 23:59? Realistically, you probably just mean for this condition to catch anything not caught by the first two conditions. If so, you really donโ€™t need a condition at all, you just need a way to catch everything:

IFS(
  [Start Time] < "12:00:00",
    โ€œMorning (8AM-Noon)โ€,
  [Start Time] < "16:00:00",
    โ€œMidday (Noon-4PM)โ€,
  TRUE,
    โ€œEvening (4PM-8PM)โ€,
)

View solution in original post

3 REPLIES 3

EDIT:

Fixed this. I think I saw the trees but missed the forest on this one. Looks like the time column automatically does stay as time as long as only the TIME() function is used.

In other words, I didnโ€™t need to extract the hour by using the HOUR() function and was able to get very specific on cutoff times (i.e. 11:59:00 as the upper limit for an AM shift).

Solution below and Iโ€™m happy to close this topic, but figured Iโ€™d leave it in case anybody else runs into a similar issue.

IFS(
TIME([Start Time])<TIME(12:00:00), โ€œMorning (8AM-Noon)โ€,
AND(
TIME([Start Time])>TIME(11:59:59), TIME([Start Time])<TIME(16:00:00)), โ€œMidday (Noon-4PM)โ€,
AND(
TIME([Start Time])>TIME(15:59:59), TIME([Start Time])<TIME(23:59:59)), โ€œEvening (4PM-8PM)โ€,
)

Steve
Platinum 4
Platinum 4

This suggests the column type is DateTime. If you change the column type to Time, you wonโ€™t have to worry about the unwanted (and potentially problematic) date component.

Hereโ€™s your express reformatted the way I prefer (just aesthetics, not functional):

IFS(
  TIME([Start Time]) < TIME(12:00:00),
    โ€œMorning (8AM-Noon)โ€,
  AND(
    TIME([Start Time]) > TIME(11:59:59),
    TIME([Start Time]) < TIME(16:00:00)
  ),
    โ€œMidday (Noon-4PM)โ€,
  AND(
    TIME([Start Time]) > TIME(15:59:59),
    TIME([Start Time]) < TIME(23:59:59)
  ),
    โ€œEvening (4PM-8PM)โ€,
)

If you change the column type of the Start Time column to Time, you wonโ€™t need to wrap it in TIME():

IFS(
  [Start Time] < TIME(12:00:00),
    โ€œMorning (8AM-Noon)โ€,
  AND(
    [Start Time] > TIME(11:59:59),
    [Start Time] < TIME(16:00:00)
  ),
    โ€œMidday (Noon-4PM)โ€,
  AND(
    [Start Time] > TIME(15:59:59),
    [Start Time] < TIME(23:59:59)
  ),
    โ€œEvening (4PM-8PM)โ€,
)

Wrapping literal times in TIME() is unnecessary, but it is good idea to put literal times in quotes:

IFS(
  [Start Time] < "12:00:00",
    โ€œMorning (8AM-Noon)โ€,
  AND(
    [Start Time] > "11:59:59",
    [Start Time] < "16:00:00"
  ),
    โ€œMidday (Noon-4PM)โ€,
  AND(
    [Start Time] > "15:59:59",
    [Start Time] < "23:59:59"
  ),
    โ€œEvening (4PM-8PM)โ€,
)

The logic in your expression could be simplified as well.

Each condition in an IFS() expression is mutually exclusive and evaluated in order. If the first condition is TRUE, no other conditions are evaluated. Only if the first condition is FALSE is the second condition evaluated.

Your first condition asks, is the start time before 12:00? Your second condition asks, is the start time after 11:59? If the second condition is evaluated, we know the first condition was FALSE, meaning we know the start time is not before 12:00, which is the same as saying it is after 11:59. So asking whether itโ€™s after 11:59 is unneededโ€“we know it is because the first condition was FALSE.

Given that, in the second and third conditions for IFS(), we donโ€™t need to ask the questions already answered by the failure of the previous conditions. This then gives you:

IFS(
  [Start Time] < "12:00:00",
    โ€œMorning (8AM-Noon)โ€,
  [Start Time] < "16:00:00",
    โ€œMidday (Noon-4PM)โ€,
  [Start Time] < "23:59:59",
    โ€œEvening (4PM-8PM)โ€,
)

The last condition asks, is the start time before 23:59? Realistically, you probably just mean for this condition to catch anything not caught by the first two conditions. If so, you really donโ€™t need a condition at all, you just need a way to catch everything:

IFS(
  [Start Time] < "12:00:00",
    โ€œMorning (8AM-Noon)โ€,
  [Start Time] < "16:00:00",
    โ€œMidday (Noon-4PM)โ€,
  TRUE,
    โ€œEvening (4PM-8PM)โ€,
)

Steve, understood and I sincerely appreciate the time you took to type this out. Will update this way and looking forward to getting a first version of an app done shortly!

Top Labels in this Space