Shop OBEX P1 Docs P2 Docs Learn Events
SNTP suddenly returning 2/1/2014 00:01:58 all the time - Page 2 — Parallax Forums

SNTP suddenly returning 2/1/2014 00:01:58 all the time

2»

Comments

  • xanatosxanatos Posts: 1,120
    edited 2013-12-09 16:48
    Well, here's the code in PUB HumanTime in SNTP 2.01:
    PUB HumanTime(Offset,TimeStampAddress)|i,Seconds,Days,Years,LYrs,DW,DD,HH,MM,SS,Month,Date,Year
        Seconds := long[TimeStampAddress] + Offset * 3600
        Days    := ((Seconds >>= 7)/675) + 1 '<- Days since Jan 1, 1900 ... divide by 86,400 (sec/day) and add 1
    

    So if we get a seconds-since time from the NTP server, and there are 86,400 seconds per day... The Days := line seems to say in the comments that they are dividing the Seconds by 86,400 - but the actual line is ((Seconds >>= 7)/675) + 1

    Are those two operations functionally equivalent?

    Seconds >>= 7 should be the same as dividing Seconds by 128, am I correct in that understanding?

    Then further dividing that result by 675 is supposed to result in the Days count. Yes?

    That's the code to which I refer. Take a look at SNTP 2.01 above which is where this all comes from...

    So when I replace the ((Seconds >>= 7)/675) + 1 with (Seconds / 86400) + 1 - I do not get the same results at all.

    Dave
  • RforbesRforbes Posts: 281
    edited 2013-12-09 17:35
    Are those two operations functionally equivalent?
    Yes.
    Seconds >>= 7 should be the same as dividing Seconds by 128, am I correct in that understanding?
    Yes.
    Then further dividing that result by 675 is supposed to result in the Days count. Yes?
    Yes.
    So when I replace the ((Seconds >>= 7)/675) + 1 with (Seconds / 86400) + 1 - I do not get the same results at all.

    I have a sneaky suspicion that if I answered that, I would be wrong. :) But, I think it's because the initial value in seconds is too large. That's why Seconds >>=7 is important. It shifts the bits, which clears a few of them on the left. I don't understand it well enough to give you a factual explanation. Maybe someone else will chime in.

    As an aside, the maximum date and time NTP supports is:
    Date/time: 2038, jan 19, 03:14:07
    ntp seconds: 4356472447.
    binary: % 1_0000_0011_1010_1010_0111_1110_0111_1111 (33 bits)

    The last second of today
    Date/time: 2013, dec 9, 23:59:59
    ntp seconds: 3595622399
    binary: % 1101_0110_0101_0000_1101_0111_1111_1111 (32 bits)
  • xanatosxanatos Posts: 1,120
    edited 2013-12-09 18:18
    Oddly enough, the Last Second of Today NTP value of ntp seconds: 3595622399, with my zone set to GMT (0) yields a time of 12/09/2013 02:00:22 through my HumanTime method.

    How are you arriving at those NTP time values? It would be handy for me to know - unless you're just multiplying out... (years * 31,536,000 secs per year) + (days this year * 86,400 secs per day) + (hours today * 3600) + (mins * 60) + seconds ...???

    3,563,568,000 + 29,548,800 + 75,600 + 360 + 45 = 3,593,192,805 is what I calculate for 2013/12/09 21:06:45

    Is that right?

    Of course, then I need to look at years/4 to get leap years and add that to days... so 113/4 = 28 leap days, x 84,600 secs/day = 2,419,200

    Then I get 3,595,612,005

    But plugging that into my HumanTime method yields a time of 2013/12/09 02:14/12

    I'm utterly confused...

    On the bright side, commenting out my "replacement Seconds" value and taking in the value from the NTP server IS yielding the correct time and date... I just don't trust it to remain correct now.......
  • RforbesRforbes Posts: 281
    edited 2013-12-09 18:39
    I cheat. http://www.aelius.com/njh/unixtime/ :) It hasn't led me wrong yet. The numbers I give you are actually from my humantime method. But I bounce them with this link just to double check.
    Then I get 3,595,612,005
    This is correct. It's the NTP value when it's 2013/12/09 21:06:45 GMT ... NTP time is always spitting out the GMT time. Always and forever. Or at least until sometime in 2038 :)
    But plugging that into my HumanTime method yields a time of 2013/12/09 02:14/12
    That's because it doesn't work correctly. (Blah hahaha!!! Sorry, I couldn't resist. that was waaaaaay too easy to pass up.) ;)

    P.S. 1900 was not a leap year. I'm not sure how/if that affects your humantime.
  • xanatosxanatos Posts: 1,120
    edited 2013-12-09 18:54
    LOL... yeah. OK, so my HumanTime doesn't work correctly. Unless I take in the actual NTP value from the server and then it IS giving me the right time.

    So.... I replace the NTP TransmitTimestamp with the calculated (and verified) value, and it gives me the wrong time. But I let the NTP value go through without replacing it and it's correct.

    I think I've had it for tonight. Maybe a beer will help me figure it out! LOL

    Thanks for your help so far, it's been tremendously valuable in helping me to figure out what's going on. I understand a LOT more about the whole thing than I did this morning, so that's success in itself.

    My main issue now is that while I understand a good chunk of what's going on, AND I have the time stamp function *seemingly* working - I am getting a good time and date - I don't trust it now. I'm hesitant to deploy what I've found because I am pretty sure it will fail at some future date - due to the fact that there's apparently SOME thing remaining that I just am not seeing/understanding (like why the passed value displays proper time/date, but the calculated value does not).

    Thanks for the link. More playtime tomorrow.

    Dave
  • Mike GMike G Posts: 2,702
    edited 2013-12-10 04:22
    My main issue now is that while I understand a good chunk of what's going on, AND I have the time stamp function *seemingly* working - I am getting a good time and date - I don't trust it now. I'm hesitant to deploy what I've found because I am pretty sure it will fail at some future date - due to the fact that there's apparently SOME thing remaining that I just am not seeing/understanding (like why the passed value displays proper time/date, but the calculated value does not).
    That's why unit tests are a good idea...

    I live by unit test as they validate code, check for edge cases like 2/29/2012, and clearly show intent. Anyway, there also an excel workbook attached used to get the math right and validate the SPIN logic.

    The idea behind ((Seconds >>= 7)/675) is to shift bit 31 to the right. Bit 31 determine if the 32 bit value is negative or positive.
  • xanatosxanatos Posts: 1,120
    edited 2013-12-10 18:19
    It's just December. For all dates in the month of December, I need to subtract 1 from "Years" in HumanTime. Once it's January, that -1 yields the wrong result. Removing it then gives the correct date.

    This is fascinating, although frustrating. I'm trying to visualize what's happening at the byte level that makes December "Special". It's given me a great level of insight into the workings of SNTP!
    PUB HumanTime(Offset,TimeStampAddress)|i,Seconds,Days,Years,LYrs,DW,DD,HH,MM,SS,Month,Date,Year
        Seconds := (long[TimeStampAddress] + (Offset * 3600)) 'Offset = Zone.  3600 secs per hr.
        'Seconds := (864000000 * 4) + (31536000 * 5)  '07/07/2013 20:57:02
        'Seconds := 3595622399 ' 2013/12/09, 23:59:59
        'Seconds := 3595612005 ' calculated as 2013/12/09 21:06:45 - but reads 2013/12/09 02:14/12 here.......
        Seconds := 3597618600
    
        Days    := ((Seconds >>= 7)/675) + 1 '<- Days since Jan 1, 1900 ... divide by 86,400 (sec/day) and add 1
                                                                                     ' 31,536,000 secs/yr
        DW      := (Days-1)//7+1    '   DW      := (Days-1)//7+1    'DW      := (Days-1) // 7
        
        Years := (Days / 365) '- 1   '   Number of Days THIS year and  ''*** Added the " - 1 " and date is good... as long as it's December.
    
    ....
    
    
  • RforbesRforbes Posts: 281
    edited 2013-12-10 18:53
    Ok... so right off the bat- if you use the ntp value of 3 595 612 005 it *should* resolve to 2013, Dec 19, 21:06:45. in GMT

    Right off the first equation, (Seconds >>=7) = 28090718
    Then / 675 = 41615
    and
    +1 = 41616

    ... then 41616 / 365 = 114 years, which is incorrect.

    but if you do this: 41616 / 1460 where 1460 is the number of days to make 1 leap day, you get 28. note:1460 = 365*4years

    Now 41616 - 28 leap days = 41588 .... and 41588 / 365 = 113 years.

    That help any?
  • xanatosxanatos Posts: 1,120
    edited 2013-12-10 19:11
    That seems to have worked. Taking a live NTP stamp, it's yielding the correct time and date. Here's the edited HumanTime method with your observations included (and previous stuff commented):
    PUB HumanTime(Offset,TimeStampAddress)|i,Seconds,Days,Years,LYrs,DW,DD,HH,MM,SS,Month,Date,Year
        Seconds := (long[TimeStampAddress] + (Offset * 3600)) 'Offset = Zone.  3600 secs per hr.
    
        'Seconds := 3595612005 ' calculated as 2013/12/09 21:06:45 - but reads 2013/12/09 02:14/12 here.......
    
        Days    := ((Seconds >>= 7)/675) + 1 '<- Days since Jan 1, 1900 ... divide by 86,400 (sec/day) and add 1
                                                                                     ' 31,536,000 secs/yr
    
        LYrs := Days/1460
    
        Days -= LYrs
    
        Years := Days/365
    
    
    
        DW      := (Days-1)//7+1    '   DW      := (Days-1)//7+1    'DW      := (Days-1) // 7
        
        'Years := (Days / 365) - 1   '   Number of Days THIS year and  ''*** Added the " - 1 " and date is good...
        'Days -= (Years * 365)       '   number of years since.
    
        'LYrs := Years / 4           '<- Leap years since 1900   2013 (113) and 2014 (114) both yield 28 (decimal truncated)
        Year := Years + 1900        '<- Current Year                   
    
        'Days -= LYrs                '<- Leap year Days correction
                                    '   for THIS year
    
                                    ' Days is now the Julian Date - actual number of days so far this year.
        
        repeat
          repeat i from 1 to 12     '<- Calculate number of days 
            Month := 30             '   in each month.  Stop if
             if i&1 <> (i&8)>>3     '   Month has been reached
               Month += 1
            if i == 2
               Month := 28 
            if Days =< Month        '<- When done, Days will contain
               quit                 '   the number of days so far this 
            if Days > Month         '   month.  In other words, the Date.
               Days -= Month     
    
    {
            if Days > Month         '<- When done, Days will contain
               Days -= Month        '   the number of days so far this 
            if Days =< Month        '   month.  In other words, the Date.
               quit     
    }
    
        until Days =< Month
        Month := i                  '<- Current Month               
        Date  := Days               '<- Current Date
    
    
        SS := long[TimeStampAddress] + Offset * 3600
        SS := SS -(((Years*365)*675)<<7) '<- seconds this year
             
        MM := SS / 60                        '<- minutes this year
        SS := SS - (MM * 60)                 '<- current seconds
        
        HH := MM / 60                        '<- hours this year
        MM := MM - (HH * 60)                 '<- current minutes
    
        DD := HH / 24                        '<- days this year
        HH := HH - (DD * 24)                 '<- current hour
    
        DD -= LYrs                           '<- Leap year Days correction
                                             '   for THIS year
    
        long[TimeStampAddress][2] := Month<<24+Date<<16+Year   'Giving bad date
        long[TimeStampAddress][3] := DW<<24+HH<<16+MM<<8+SS    'Giving good time                                 
    
    '    DD is redundant but I included it for completion...
    '    If you subtract the number of days so far this year from
    '    DD and add one, you should get today's date.  This is calculated
    '    from another angle above from Days
    
    

    Now I just need to test it to see what it does for a date in 2014....

    THANKS!
  • Mike GMike G Posts: 2,702
    edited 2013-12-10 19:16
    There's two things that I see...
    1) ((Seconds >>= 7)/675) is the number of day since 1/1/1900 minus the fractional part of the current day. Another way to say this is, the timestamp is whole days plus a fraction of a day. The binary shift and division truncate the fraction part of the last day.((Seconds >>= 7)/675) + 1 adds a day (86400 secs) to the SNTP timestamp minus the faction of a day.

    2) There have been 28 leap years since 1/1/1900. You're probably not accounting for leaps years in the equation Years := (Days / 365) '- 1.

    Taking Item 1 and 2 into account and realizing there have been 28 leap years since 1/1/1900, it seems to reason why the date messed up around 12/3/2013 of this year. After all the number in day in December (31)-3 = 28.
  • RforbesRforbes Posts: 281
    edited 2013-12-10 19:32
    Dave- Nope, the code you just posted doesn't work. day of week is wrong and also the day of the month. ntp 3913055999 should be 2023, dec 31, 23:59:59 and it's coming up with dec 30. day of week says 4, but it should be 1.

    The critical flaw with this approach is that we're taking a definitive value (the ntp seconds value) starting to manipulate it using numbers that aren't consistent conversions. For instance, 1460 sounds great, because we have 1 leap day every 1460 days. But that day occurs a strange time of the year. Any division by that number is only valid when you do something with the remainder... because it's significant. Worse yet, if calculations are ran before the leap day of a leap year, we do X with the remainder. Otherwise, we have to do Y with it. The problem is we don't know where we are in time until we figure it out. And to figure it out, we need... oh yeah. My head hurts now. :)

    Try to follow through my code. It works because it takes everything 1 step at a time and rolls values up or down as it goes.
  • Mike GMike G Posts: 2,702
    edited 2013-12-13 15:46
    So far so good, the update to human time is functioning as expected.
    http://174.97.235.77:5000/time.xml

    EST time, btw...
  • xanatosxanatos Posts: 1,120
    edited 2013-12-15 17:27
    I've got my units all on manual time right now, and that should suffice for the next month or so. I'm going to wait until AFTER the 1/1/2014 transition to see how these guys perform then. I've got code here on my dev system that seems to be working even with "manually substituted" NTP time values into 2014 and beyond, but I'm just very distrustful of implementing any of these just yet - and that only because while I understand a great deal of the code now, there are still gray areas I need to work to understand, and so there's still the "magic" factor in there for me :-)

    Right now I'm just in a holding pattern and onto another project while I digest what I've learned so far. I think when I return to it in January, fresh, it'll probably seem more obvious.

    Thanks again for all your help & observations. And especially for letting me know I wasn't the only one seeing the issue!!!! :-)
Sign In or Register to comment.