# Night time hours calc, which can span midnight

This topic is 2907 days old. Please don't post here. Open a new topic instead.

## Recommended Posts

I've googled far and wide and have not been able to find anything that gives clues to solving this issue. I'm trying to write a calculation which returns the number of "night time hours" for a given Punch record, which can start and/or end inside of or outside of pre-determined "night time" hours.

Our data:

A) A Punch record has two timestamp fields: ClockIn, and ClockOut. Any valid timestamps can be entered. Typically, the time stamps will be on the same day, different times, but, can also span from one day until the next day, bridging the midnight hour.

We know the time that we want to set as the beginning of "night time": For this exercise, let's set it at 9:00 PM, which is unchanging, can be hard-coded.

C) We know the time that we want to set as the end of "night time": For this exercise, let's set it at 5:00 AM, which is unchanging, can be hard-coded.

Our Scenarios. For simplicity, I'll use plain English whole numbers for times:

1) ClockIn = 10AM. ClockOut = 5PM. Calc should return "0", as none of those hours qualified for "night time" hours.

2) ClockIn = 3AM. ClockOut = 11AM. Calc should return "2", because two of those hours were during "night time" hours.

3) ClockIn = 6PM. ClockOut = 1AM the next day. Calc should return "4" because four of those hours were during "night time" hours.

4) ClockIn = 3AM. ClockOut = 11PM. Calc should return "4" because four of those hours were during "night time" hours

5) ClockIn = 3AM. ClockOut = 1AM the next day. Calc should return "7" because seven of those hours were during "night time" hours.

Scenarios #4 and #5 have defeated me. I believe it has something to do with the fact that we have two separate groups of "night time" hours separated by a chunk of not-night-time hours. The phrase "recursive function" comes to mind, but not really sure, perhaps a really healthy LET and CASE without recursion?

##### Share on other sites

You say timestamps, but you only show us times - not sure if that's significant. Can one assume no period goes over 24 hours?

##### Share on other sites

The two fields in a Punch record are timestamps, yes. My bad for over-simplifying the scenarios using plain English whole numbers for times. Here are the example scenarios again, this time using actual timestamps:

1) ClockIn = 01/01/2014 10:00:00. ClockOut =  01/01/2014 17:00:00. Calc should return "0", as none of those hours qualified for "night time" hours.

2) ClockIn =  01/01/2014 03:00:00. ClockOut = 01/01/2014 11:00:00. Calc should return "2", because two of those hours were during "night time" hours.

3) ClockIn = 01/01/2014 18:00:00. ClockOut = 01/02/2014 01:00:00 (the next day). Calc should return "4" because four of those hours were during "night time" hours.

4) ClockIn = 01/01/2014 03:00:00. ClockOut = 01/01/2014 23:00:00. Calc should return "4" because four of those hours were during "night time" hours

5) ClockIn = 01/01/2014 03:00:00. ClockOut = 01/02/2014 01:00:00 (the next day). Calc should return "7" because seven of those hours were during "night time" hours.

It is not known wether or not one period can exceed 24 hours. Let's code on the assumption that no time period will exceed 23 hours, 59 minutes, 59 seconds and a fistful of microseconds. Thank you for looking!

##### Share on other sites

Assuming there are at most two night periods to consider (the one that begins on the same day as ClockIn, and either the one before or the one after - depending upon ClockIn occurring before NightEnd or after), try the following (not tested very thoroughly) =

```Let ( [
nightStart = Time ( 21 ; 0 ; 0 ) ;
nightEnd = Time ( 5 ; 0 ; 0 ) ;

N0 = Timestamp ( GetAsDate ( ClockIn ) ; nightStart ) ;
N1 = Timestamp ( GetAsDate ( ClockIn ) + 1 ; nightEnd ) ;

direction = Case ( GetAsTime ( ClockIn ) ≥ nightEnd ; 1 ; -1 ) ;
N2 = N0 + 86400 * direction ;
N3 = N1 + 86400 * direction
] ;
Max ( Min ( N1 ; ClockOut ) - Max ( N0 ; ClockIn ) ; 0 )
+
Max ( Min ( N3 ; ClockOut ) - Max ( N2 ; ClockIn ) ; 0 )
)```

The result type should be Time.

This returns results similar to the ones in your examples, with the exception of #5 where it returns 6:00:00 - which I believe is the correct result.

• 3
##### Share on other sites

Comment, you're a genius! That works perfectly and is far more elegant than I had envisioned the answer being. And you're right about #5 - which is exactly why it's better to let computers do the math. [=
Thank you very much for your assistance. Need to buy you a beer!

##### Share on other sites

```direction = Case ( GetAsTime ( ClockIn ) ≥ nightEnd ; 1 ; -1 ) ;
N2 = N0 + 86400 * direction ;
N3 = N1 + 86400 * direction

```

I read this whole thing and I do not see where the 86400 comes from.  Can you explain this for me?  I think i understand the rest of it by looking at results in viewer individually but this figure throws me.  Thank you Comment.

##### Share on other sites

A day - 60 x 60 x 24  :-)

• 1
##### Share on other sites

Or put another way, that is the number of seconds in a day.

• 1
##### Share on other sites

It's a shortcut for Time ( 24 ; 0 ; 0 ).

• 1
##### Share on other sites

This is so good.  All of it fits.  So I wondered if time worked like dates and tried this:  Time( 0 ; 1440 ; 0 ) and it works also.  I am grateful to all of you for the variety.  I will never have a problem with time again because I actually understand this now.

1440 I mean.

Edited by Charity
##### Share on other sites

This topic is 2907 days old. Please don't post here. Open a new topic instead.

## Create an account

Register a new account

• ### Similar Content

• #### summarizing data in a portal timesheet database

• 6 replies
• 1,246 views
• #### Issues with Calendar, To-Do's, Timesheets

By Andreas Ravichandran,

• 3 replies
• 3,188 views
×
×
• Create New...