Search code examples
datetimetimestamp

How to extract the hour of day from a timestamp by hand?


No, I'm not trying to do this in any particular language. If all you have is math, is it possible to extract the hour of day from a timestamp, if so how?

Example

Here's a sample timestamp 1602934899. The expected output (the hour in that timestamp) is 11.

Edit

I'm trying to accomplish this without any libraries. Also, I'm aware of leap seconds and I don't care about the lack of precision that may be caused if I ignore it for my purposes. I also don't care for leap years or timezones or daylight savings time.


Solution

  • tl;dr

    ( 1_602_934_899L % 86_400 ) / 3_600 
    

    11

    Details

    Here's a sample timestamp 1602934899

    Such a number used for tracking a date-time values is usually a count of whole seconds, milliseconds, microseconds, nanoseconds, hundreds of microseconds, or some such granularity.

    The count of time is framed as time elapsed since an arbitrary epoch reference point. A couple dozen such points have been used by various successful computing platforms. One of the more common reference points is the one used by many Unix oriented systems, the first moment of 1970 in UTC, 1970-01-01T00:00Z. By “in UTC” we mean an offset from UTC of zero hours-minutes-seconds.

    Your number 1602934899 might well be a count of whole seconds since that epoch reference point. But do not guess! Ask the publisher of your data to be sure as to their choice of granularity and epoch reference point.

    timeline diagram showing epoch reference point of 1970-01-01T00:00Z, a point of 1,602,934,899 seconds, and the current moment of 2021-06-12T04:52:40.982078Z

    After determining the epoch reference, do the math. You can consider a day to be exactly 24 hours long, so 60 * 60 * 24 is the number of seconds per day. Dividing your input by that number gives you the number of whole days that have passed. The remainder gives you the fraction of the last day. You will need to do the math on that remainder to get a time-of-day, dividing to get the hours, minutes, and seconds.

    Since you asked only for the hour, that suffices. Getting a date is more work as leap years must be considered. But your problem statement asked only for hour, so the date is irrelevant.

    Leap seconds are irrelevant to your calculation. The point of a leap second every few years is to slow the clock a moment so as to keep our tracking of earth’s spinning (time of day) in sync with our tracking of earth’s rotation around the sun (years and days, dates) using neat packages of exactly 60 * 60 * 24 seconds. So leap seconds on the clock are meant to be swallowed by the calendar.

    By the way, doing your own date-time handling is generally ill-advised. Date-time is a surprisingly tricky subject. So using a properly designed date-time framework, such as the java.time classes in Java, is wise. However in your comments you indicated an unusual and extreme need in your work, so doing this calculation yourself may be justified.

    First, let java.time do the work, using the Java language.

    // The easy way.
    Instant instant = Instant.ofEpochSecond( 1_602_934_899L ) ;
    int h = instant.atOffset( ZoneOffset.UTC ).getHour() ;
    Duration d = Duration.between( Instant.EPOCH , instant ) ;
    
    System.out.println( instant ) ;
    System.out.println( h ) ;
    System.out.println( d ) ;
    System.out.println( d.toDaysPart() + " days, " +  d.toHoursPart() + " hours, " + d.toMinutesPart() + " minutes, " +  d.toSecondsPart() + " seconds, " +  d.toNanosPart() + " nanos." ) ;
    

    See this code run live at IdeOne.com.

    2020-10-17T11:41:39Z
    11
    PT445259H41M39S
    18552 days, 11 hours, 41 minutes, 39 seconds, 0 nanos.
    

    Now, let's crunch the numbers, also in Java.

    // The hard way.
    long days = ( 1_602_934_899L / ( 60 * 60 * 24 ) ) ;
    long secondsInPartialDay = ( 1_602_934_899L % ( 60 * 60 * 24 ) ) ;  // The percent-sign "%" means modulo in Java.
    long hour = ( secondsInPartialDay / ( 60 * 60 ) ) ;
    

    See this code run live at IdeOne.com.

    days = 18552
    secondsInPartialDay = 42099
    hour = 11
    

    Or more compactly:

    ( 1_602_934_899L % ( 60 * 60 * 24 ) ) / ( 60 * 60 )
    

    If your compiler does not optimize away the multiplications, replace with their products to do the optimization yourself.