We're In Different Timezones




  • Our application accepts data from a variety of upstream systems, all of which represent date-time values as local time in different ways. Naturally, there is conversion and time-calc code all over the place. Every now and then someone makes a change in one place but doesn't propagate it and you end up with all sorts of unpredictable behavior.

    I took it upon myself to create a date-calc facade with a bunch of overloaded methods to convert between one date/time format and another, as well as to perform assorted date/time calculations. Internally, everything was converted to GMT, the operation performed using SimpleDateFormat and/or Gregorian/Calendar, and if required, the computed value converted back to local time on the way back out. I asked someone else to create a comprehensive test suite including all sorts of combinations of good and bad data and edge cases. This had the added benefit of encapsulating GMT vs local time, daylight savings time, and so forth.

    We rigorously tested it, got management blessing, deployed it to all development servers, sent detailed documentation on how to use it and code samples for every wrapper function to all development teams, and had a webex to walk folks through using it and answer questions.

    A while later we noticed some checkins from a developer (who had received the training) with code to do his own date-diff calculations.

    When asked why he was writing his own date code after he been instructed on the use of the date facade, he replied that we were in different timezones. As such, the difference between our time and GMT is different than the difference between his time and GMT, so my calculations won't work.

    He didn't bother to communicate his perceived problem; he just ignored the situation and rolled his own.

    Happy New Year to one and all!!!



  • Meet the new year, same as the old year.

     



  • he operation performed using SimpleDateFormat and/or Gregorian/Calendar,

    This is TRWTF... please, save yourself and fellow programmers the pain and use JodaTime, thanks from 2012.



  • Perpetuum mobile... This driving force is the major reason why there is so much dull work out there. Our clients re-invent everything from floating point arithmetics to databases in various fundamentally flawed and incomplete ways just because they can't seem to figure out how any existing solution works, let alone use them for anything good. Better invent a new inner platform! Systems designed for amateurs by amateurs, can't get any better.



  • @ubersoldat said:

    he operation performed using SimpleDateFormat and/or Gregorian/Calendar,

    This is TRWTF... please, save yourself and fellow programmers the pain and use JodaTime, thanks from 2012.

     

     I would, if JodaTime classes were supported by JDK classes. As it is, Calendar and Date will have to do unless I want to do some really icky date stuff, which is rarely.



  • Well, calculations involving time and timezones are, in fact, very nasty.

    I just recently realized that the result of executing the following SQL statement on an oracle database depends on what timezone your client software runs in:

    select * from SOME_TABLE where CREATED_AT < systimestamp

    where CREATED_AT is defined as a TIMESTAMP data type. The reason is that SYSTIMESTAMP is not of type TIMESTAMP (which is defined as containing date-and-time), but rather of type TIMESTAMPTZ (which is defined as a date-and-time-and-timezone), and the statement execution parser implicitly coerces these two data types to the more specific one (TIMESTAMPTZ), and, to that purpose, converts the CREATED_AT field to a TIMESTAMPTZ using the timezone of the client session.

    That behavior was rather unexpected, and it cost me a few days of debugging and searching and RTFM to figure that out.

    My corollary is that type TIMESTAMP should never be used, or you need to make sure that all timestamps are stored in UTC, so you can convert that easily to any other timezone. I figure it is much easier to always use TIMESTAMPTZ -- then you at least know what timezone you are talking about.



  • TRWTF is the ludicrously unwieldy calendar and time system we've ended up with, thanks to the stupid ancients not having the foresight to predict how computers would work.  I urge all of you to do everything in your power to persuade your employers to adopt stardates.


  • Garbage Person

    @Iago said:

    I urge all of you to do everything in your power to persuade your employers to adopt stardates.
    Ah, stardates. The only calendaring system I've ever heard of where the fucking numbers are absolutely arbitrary.



  • I have become convinced that all timestamps (anything with a date and a time both) should carry a time zone indicator. And, of course, since MySQL datetime and timestamp don't have time zones, well, I had to roll my own.

    Suppose my daughter in California posts to a forum, and the server is in New York, and I view the page in Thailand. The timestamp shows no time zone. Is it GMT? Or is it local time? And is it my local time, or her local time, or the server's local time? One never knows.

    (Just this morning I spent an hour debugging a call to mktime(); turns out that the arguments are local time but the result is GMT. Switched to gmmktime() and the bug disappeared. Even though the entire calculation is being done in the wrong timezone, it is the same time zone both in and out.)

     



  • The TRWTF are timezones. Period.



  • @AndyCanfield said:

    (Just this morning I spent an hour debugging a call to mktime(); turns out that the arguments are local time but the result is GMT. Switched to gmmktime() and the bug disappeared. Even though the entire calculation is being done in the wrong timezone, it is the same time zone both in and out.)

    mktime() and gmmktime() both return Unix timestamps, which are independent of time zone (being just a count of elapsed seconds since 1970-01-01T00:00:00+0000). The difference is that the former assumes arguments are given wrt the local time zone, while the latter expects them relative to UTC. Needless to say, the "local time zone" is whatever the server has been told it is.

     



  • @Watson said:

    mktime() and gmmktime() both return Unix timestamps, which are independent of time zone (being just a count of elapsed seconds since 1970-01-01T00:00:00+0000).
     

    I quibble with your use of the phrase "independent of time zone". Indeed, your explanation refers to "1970-01-01T00:00:00+0000". That's GMT at the tail end there, that "+0000". A 'now' Unix timestamp may be the same all over the world (independent of time zone) because they all are dependent on the same time zone (GMT).

    In the bug I had, I called mktime( 0, 0, 0, ThisMonth, ThisDay, ThisYear ) and was surprised to get an integer which was not a multiple of 86400. The remainder, when divided by 86400, gave me 17 hours, which is 24 - 7, and I recognized that 7 hours East of GMT is my time zone (ICT).  That's when I realized my error.

    What I was incorrectly expecting was the number of seconds since 1970-01-01T00:00:00 ICT.

    I had to change to gmmktime. In effect I am lying to gmmktime telling it that ThisMonth, ThisDay, and ThisYear are GMT, when in fact they are not, they are ICT. Then I keep subtracting 86400 until I get a Monday. The whole purpose was to find out the date of the most recent Monday.

    The first line of my post was that all timestamps should have time zone in them. You mention "number of seconds since 1970-01-01T00:00:00+0000". There you have one; a timestamp with a time zone in it ("+0000"). Timestamps without an explicit time zone lead to confusion.

     



  • @Weng said:

    @Iago said:

    I urge all of you to do everything in your power to persuade your employers to adopt stardates.
    Ah, stardates. The only calendaring system I've ever heard of where the fucking numbers are absolutely arbitrary.

     

    "Captain's Log, stardate "+ (Math.random() * 100) +"."

     


  • Garbage Person

    @dhromed said:

    "Captain's Log, stardate "+ (Math.random() * 100) +"."
    Not quite. A stardate usually (but doesn't always) has a decimal component to the tenths place.



  • @AndyCanfield said:

    The whole purpose was to find out the date of the most recent Monday.

     

    Excuse me ... but why not simply do a localtime(time(NULL)), look at the day-of-week value, and then go 86400*N seconds back, to do localtime() from the new value again?

     



  •  Real man convert dates to JDN and do all their calculations from there.

    For example, figuring out the number of sundays and saturdays between 2 dates:

    function jdn($d,$m,$y) {
        $a=floor((14-$m)/12);
        $yy=$y+4800-$a;
        $mm=$m+12*$a-3;
        $res=$d+floor((153*$mm+2)/5)
            +365*$yy
            +floor($yy/4)
            -floor($yy/100)
            +floor($yy/400)
            -32045;
        return($res);
    }

    function num_sun_sat($date1,$date2) {
      list($d,$m,$y)=explode('/',$date1);  $d1=jdn($d,$m,$y);
      list($d,$m,$y)=explode('/',$date2);  $d2=jdn($d,$m,$y);

      $res=(floor($d2/7)-floor($d1/7))*2
        -max(0,$d1%7-5)
        +max(0,$d2%7-4);

      return($res);
    };
     </pre>



  • @AndyCanfield said:

    Suppose my daughter in California posts to a forum, and the server is in New York, and I view the page in Thailand. The timestamp shows no time zone. Is it GMT? Or is it local time? And is it my local time, or her local time, or the server's local time? One never knows.

    Sure you do; the server's time zone is authoritative. That's how a sane person would design it. If you're getting the timestamp from the client, instead of having the server generate it-- you're doing something wrong. If you're sending the server's timestamp to the client without letting the client correct for time zone-- you're doing something wrong. This is a solved problem.

    The real problem comes when you have servers in different time zones. And the servers talk to each other. That is less solved. What we do is just arbitrarily declare all servers are in EST, regardless of where they are actually physically located.



  • @bdew said:

    Real man convert dates to JDN

    JDN is fine, as long as:

    1) You document that it's JDN (because oddly, it turns out a lot of people are never exposed to JDN dates and don't recognize them.)

    2) You don't rely on any of the peripheral information you get with timezones, for example, in the US the time zone tells you whether it's daylight saving time or not and gives a sense of vague physical location.

    @bdew said:

    function jdn($d,$m,$y) {
        $a=floor((14-$m)/12);
        $yy=$y+4800-$a;
        $mm=$m+12*$a-3;

    Is that PHP? Why would a real man be using PHP?

    This just doesn't add up.



  • @AndyCanfield said:

    I quibble with your use of the phrase "independent of time zone". Indeed, your explanation refers to "1970-01-01T00:00:00+0000". That's GMT at the tail end there, that "+0000". A 'now' Unix timestamp may be the same all over the world (independent of time zone) because they all are dependent on the same time zone (GMT).

    In the bug I had, I called mktime( 0, 0, 0, ThisMonth, ThisDay, ThisYear ) and was surprised to get an integer which was not a multiple of 86400. The remainder, when divided by 86400, gave me 17 hours, which is 24 - 7, and I recognized that 7 hours East of GMT is my time zone (ICT).  That's when I realized my error.

    What I was incorrectly expecting was the number of seconds since 1970-01-01T00:00:00 ICT.

    I had to change to gmmktime. In effect I am lying to gmmktime telling it that ThisMonth, ThisDay, and ThisYear are GMT, when in fact they are not, they are ICT. Then I keep subtracting 86400 until I get a Monday. The whole purpose was to find out the date of the most recent Monday.

    The first line of my post was that all timestamps should have time zone in them. You mention "number of seconds since 1970-01-01T00:00:00+0000". There you have one; a timestamp with a time zone in it ("+0000"). Timestamps without an explicit time zone lead to confusion.

     

    What AndyCanfield is saying.



  • @blakeyrat said:

    Is that PHP? Why would a real man be using PHP?
     

    Well it allows you to shoot yourself in the foot with the easyness only a dynamic typed language * can give, while letting you keep all those crazy $symbols ++and {curly {braces $everywhere}}}, so your !== ((code === looks) || (like && someone || spilled)) some Perl &= over your C. Ah and you can interlay your code with your template and run db queries in the middle of outputting an HTML attribute value!

     



  • @blakeyrat said:

    Is that PHP? Why would a real man be using PHP?

    Because real men insist on doing everything the wrong way lest anyone question their masculinity.



  • @bdew said:

    Ah and you can interlay your code with your template and run db queries in the middle of outputting an HTML attribute value!
     

    That's just what it looks like when you open the file.

    At least, that's how it works in ASP-classic, where everything that's not ASP is wrapped in a writeBlock(blockIndex) call, so that when the ASP preparser is done with the file, there is no plain HTML anywhere, just pure code that adds strings to the buffer.

    I can only assume a smiliar mechanism exists in PHP/Zend.

    That is, I can only assume because I'm too lazy to hit up the webs and find out.



  • @blakeyrat said:

    Sure you do; the server's time zone is authoritative. That's how a sane person would design it.
    Bwahahahaha!
    If you're getting the timestamp from the client, instead of having the server generate it-- you're doing something wrong. If you're sending the server's timestamp to the client without letting the client correct for time zone-- you're doing something wrong. This is a solved problem.

    The real problem comes when you have servers in different time zones. And the servers talk to each other.

    Or you're writing a web app, which might be run on a shared webhost.  Or, really, any situation where the person(s) responsible for maintaining the application don't also have full control over the server(s) it runs on.  The only safe and sane thing to do in that situation is to treat the server's time zone as a random value that may be anything and is subject to change at any time for any or no reason.
    That is less solved. What we do is just arbitrarily declare all servers are in EST, regardless of where they are actually physically located.
    That sounds almost reasonable... except why go for EST instead of UTC, if you're going to pick an arbitrary time zone anyway?



  • @vyznev said:

    @blakeyrat said:
    Sure you do; the server's time zone is authoritative. That's how a sane person would design it.
    Bwahahahaha!

    Because you think my solution is bad, or because systems are never designed by sane people?

    @vyznev said:

    If you're getting the timestamp from the client, instead of having the server generate it-- you're doing something wrong. If you're sending the server's timestamp to the client without letting the client correct for time zone-- you're doing something wrong. This is a solved problem.

    The real problem comes when you have servers in different time zones. And the servers talk to each other.

    Or you're writing a web app, which might be run on a shared webhost.

    Being a web app doesn't change anything I just said. This web app we're using right now, despite being extraordinarily crappy in almost every way, seems to manage it ok.

    @vyznev said:

    Or, really, any situation where the person(s) responsible for maintaining the application don't also have full control over the server(s) it runs on.

    Yes, that could be a problem. All you can do in that case is put the time zone change in the deployment instructions and hope and pray the guy installing it actually read the instructions.

    @vyznev said:

    That sounds almost reasonable... except why go for EST instead of UTC, if you're going to pick an arbitrary time zone anyway?

    I dunno. I inherited this system. What's even weirder is that it was all designed (and the first few clusters of servers were located) in Seattle. So why not PST? Who knows.



  • No matter how badly your system handles timezones and timestamps, it can't be worse than SAP. (Or at least how my company uses SAP.)

    Once a year, we have to shut down all of our production systems -- our global production systems -- in order to survive the cataclysm that is daylight saving time. The shift from EST to EDT has world-wide implications for our business. No orders, invoices, shipping labels, nothing, across the entire globe for a full hour. We're a large international company in the Fortune 500. Sigh.


  • Discourse touched me in a no-no place

    @Xyro said:

    Once a year, we have to shut down all of our production systems -- our global production systems -- in order to survive the cataclysm that is daylight saving time. The shift from EST to EDT has world-wide implications for our business. No orders, invoices, shipping labels, nothing, across the entire globe for a full hour.
    What happens on the EDT to EST change, where an hour is repeated?



  • @PJH said:

    @Xyro said:
    Once a year, we have to shut down all of our production systems -- our global production systems -- in order to survive the cataclysm that is daylight saving time. The shift from EST to EDT has world-wide implications for our business. No orders, invoices, shipping labels, nothing, across the entire globe for a full hour.
    What happens on the EDT to EST change, where an hour is repeated?

    Uuuhhm,... oh wait, that's the one I meant. Gosh, it confused me, just imagine what it would do to a computer!



  • @PJH said:

    What happens on the EDT to EST change, where an hour is repeated?
    Isn't that how we get duplicate posts?



  • TRWTF is that there are virtually no systems that properly represent local time historically.... Quick What was local time delta in Boise, Idaho in 1953 on Septeber 5th?



  • @TheCPUWizard said:

    TRWTF is that there are virtually no systems that properly represent local time historically.... Quick What was local time delta in Boise, Idaho in 1953 on Septeber 5th?

    Trick question! "Septeber" isn't a month.



  • @blakeyrat said:

    @TheCPUWizard said:
    TRWTF is that there are virtually no systems that properly represent local time historically.... Quick What was local time delta in Boise, Idaho in 1953 on Septeber 5th?

    Trick question! "Septeber" isn't a month.

     

    Not only that, but the Boise River doesn't have a delta.



  • @flop said:

    @AndyCanfield said:

    The whole purpose was to find out the date of the most recent Monday.

     

    Excuse me ... but why not simply do a localtime(time(NULL)), look at the day-of-week value, and then go 86400*N seconds back, to do localtime() from the new value again?

     

    Yeah, that would do it too. Be careful, though, because on Sunday gives N = 1; in that case you have to back off N+7 days. The code "while Weekday(T) != Monday set T -= 86400" has no edge case like that, and executes a maximum of six times which is not bad. 

     



  • I recall a recent Slashdot posting about historical time zone data being the subject of copyright issues by astrologers.

    here it is: http://yro.slashdot.org/story/11/10/06/1743226/Civil-Suit-Filed-Involving-the-Time-Zone-Database



  • @blakeyrat said:

    @AndyCanfield said:
    The timestamp shows no time zone. Is it GMT? Or is it local time? And is it my local time, or her local time, or the server's local time? One never knows.

    Sure you do; the server's time zone is authoritative. That's how a sane person would design it.

     

    My question related to what is displayed on the user's screen. This web site itself, thedailywtf.com, changes posting timestamps to match the time zone of the viewer. The Dyn.com web site shows timestamps in the time zone of the server. I did not know where the server was until I worked out that my updates were shown according to Eastern US time. This posting is being written at "Wed Jan  4 07:24:08 2012" (ICT) and that string will remain as the poster's local time and not be adjusted.

    When you see a time stamp without a time zone, you have to assume what the time zone is, and your assumption can very very easily be wrong. Again I recommend that all timestamps show the time zone.

     



  • @AndyCanfield said:

    Again I recommend that all timestamps show the time zone.

    I recommend that all timestamps that aren't adjusted to the viewer's TZ show the TZ.


  • @AndyCanfield said:

    This web site itself, thedailywtf.com, changes posting timestamps to match the time zone of the viewer.

    It still gets it wrong - for example assuming the entire world has daylight savings at the same time. (Hint: my state does not have daylight savings, plus if it did it would be exactly opposite its assumption, being in the southern hemisphere and all)



  • @Zemm said:

    It still gets it wrong - for example assuming the entire world has daylight savings at the same time.
     

    Daylight savings time is another big headache. I live in Thailand which has no daylight savings time and is exactly twelve hours ahead of Eastern Standard Time. So we are either 12, or maybe 11, or maybe 13, hours ahead of New York time depending on the date of the year and the phase of the moon and the entrails of the chicken. A couple of years ago the Feds changed the date for the EST/EDT switch and EVERY COMPUTER ON THE ENTIRE PLANET had to be updated (plus a few not on the planet).



  • @AndyCanfield said:

    A couple of years ago the Feds changed the date for the EST/EDT switch and EVERY COMPUTER ON THE ENTIRE PLANET had to be updated (plus a few not on the planet).
     

    Mine didn't.  The only thing I had to screw with is the same thing I have to screw with twice a year anyway: timers for recording radio and television shows that are broadcast from some place that does DST (local shows are nice enough to stay put).  And "spring forward, fall back" doesn't help your memory when you're making that kind of adjustments.



  • @AndyCanfield said:

    @Watson said:

    mktime() and gmmktime() both return Unix timestamps, which are independent of time zone (being just a count of elapsed seconds since 1970-01-01T00:00:00+0000).
     

    I quibble with your use of the phrase "independent of time zone". Indeed, your explanation refers to "1970-01-01T00:00:00+0000". That's GMT at the tail end there, that "+0000". A 'now' Unix timestamp may be the same all over the world (independent of time zone) because they all are dependent on the same time zone (GMT).

    What I meant by "independent of time zone" was indeed that the same moment is represented by the same timestamp no matter what time zone you're in. And yes, it does that by specifying a time zone - the same one independent of whichever one you happen to be using locally. If all timestamps used the same timezone then mentioning it would not be necessary except when making the timestamp's format explicit (as I was doing).

    In the bug I had, I called mktime( 0, 0, 0, ThisMonth, ThisDay, ThisYear ) and was surprised to get an integer which was not a multiple of 86400. The remainder, when divided by 86400, gave me 17 hours, which is 24 - 7, and I recognized that 7 hours East of GMT is my time zone (ICT).  That's when I realized my error.
    Of course; because if you're seven hours east of UTC then local (i.e. where you are) midnight occurs seven hours earlier than UTC midnight. So it's not surprising that what you got was seven hours shy of a full day: there were still seven hours to go before midnight.

    What I was incorrectly expecting was the number of seconds since 1970-01-01T00:00:00 ICT.
    And why would you expect that? Unix timestamps aren't defined in terms of ICT.

    Then I keep subtracting 86400 until I get a Monday. The whole purpose was to find out the date of the most recent Monday.
    If on Monday "today" qualifies as "most recent Monday", then date('Y-m-d', strtotime(date('w') == 1 ? 'today' : 'last Monday'));. If not, the conditional and therefore the magic number (Monday is the 1st day of the week) can be dropped.

    Timestamps without an explicit time zone lead to confusion.
    Only if there can be a confusion about which timezone is being used.

     



  • @Watson said:

    If all timestamps used the same timezone then mentioning it would not be necessary except when making the timestamp's format explicit (as I was doing).
    All timestamps are GMT/UTC* unless otherwise stated, by convention that predates computers by decades - the Prime Meridian was universally agreed in 1884, but only because by then it had been adopted in practice anyway. This convention is widely abused by programmers, but is still the case in pretty much any other field.


    [* For the purposes of this discussion, they're the same thing.]



  • @MascarponeRun said:

    @Watson said:
    If all timestamps used the same timezone then mentioning it would not be necessary except when making the timestamp's format explicit (as I was doing).
    All timestamps are GMT/UTC* unless otherwise stated,

    Which was basically my point: AndyCanfield was right in that his mistake was thinking that timestamps varied by timezone.

    Since all timestamps are based off the same timezone there's no need to keep specifying which one it is.


Log in to reply