1

I have a jQuery app that sends a date object to python for parsing. The problem is that when I try to use my jQuery on the Windows machine, the date object looks like this:

Tue Mar 12 2013 00:00:00 GMT-0600(Mountain Daylight Time)

Whereas on my Mac, I get:

Tue Mar 12 2013 00:00:00 GMT-0600(PST)

When I try to parse these in Python with the strptime function, it fails because it doesn't understand the time zones on the end of the first (the MDT one). It complains that is an "unknown string format".

How do I resolve this? Am I doing something wrong?

Sean Vieira
  • 155,703
  • 32
  • 311
  • 293
Garfonzo
  • 3,876
  • 6
  • 43
  • 78
  • 1
    Have you tried using Unix time? That way you'll always be able to avoid regionality issues and whatever printing inconsistencies that'll get in your way. http://en.wikipedia.org/wiki/Unix_time – Marc Laugharn Mar 22 '13 at 23:30
  • @MarcLaugharn: I'm actually looking into that right now. Trying to create a UTC date object in jQuery to then pass to python. Really, I don't care about the time zone at all -- if I could ignore it all together, that'd be ideal. But I think I need to manage it, so I want to do it correctly. – Garfonzo Mar 22 '13 at 23:32
  • @Garfonzo http://stackoverflow.com/questions/847185/convert-a-unix-timestamp-to-time-in-javascript – John Mar 22 '13 at 23:33
  • `strptime` doesn't really understand the "PST" timezone either. If you need to parse it, you will need to use a separate timezone (or date parse) library. If you don't need it (e.g., because you're only dealing in local times from a single timezone—although that seems unlikely given that your two examples have two different timezones…) the simplest thing to do is strip it off first, then parse. – abarnert Mar 22 '13 at 23:33
  • 2
    At any rate, it's almost always best to pass around UTC dates, or pass timezones and "naive" local dates as separate objects, instead of trying to pass timezone-equipped local dates. – abarnert Mar 22 '13 at 23:36
  • @abarnert: Originally, I built everything in one time zone and simply parsed over the extra: `GMT-0600(PST)`. Now that I'm in another time zone and my code is failing, I'm seeing the flaw in my original design. However, I don't think I can simply strip if off and ignore it because as soon as I parse it as a date again, the time zone will show up (like in the python side of things). – Garfonzo Mar 22 '13 at 23:36
  • @Garfonzo: Well, if you don't need DST and historical information, you can parse the `GMT-0600` part and skip over the `(PST)` part, which solves the problem without requiring a radical change to your design. (Also, it's worth pointing out that the `tzinfo` objects in `datetime` do not handle DST and historical information anyway; you need `pytz` or some other third-party library anyway. Plus, of course, yet another library to parse non-standard timezones into Olson timezones for `pytz` to use.) – abarnert Mar 22 '13 at 23:42
  • @abarnert: Ya, that seems to be the best solution -- however, how do I "skip over" the time zone information when its large, as in my example with `Mountain Daylight Time`? Do I convert the date object to a string, then only use the first `X` characters? Wouldn't the server runing the python code, when it parses the new chopped string, then apply a time zone and I'd be back to square one? – Garfonzo Mar 22 '13 at 23:45
  • I was actually suggesting letting the jQuery client stick whatever it wants there, then changing the Python code to strip it off (which could be as simple as `s.partition('(')[0]`) before calling `strptime`. – abarnert Mar 22 '13 at 23:47
  • Meanwhile, `strptime` always gives you naive `datetime` objects. Instead of trying to fix that and build an aware object, just trust the -0600 to be all you need to convert to GMT, and use the GMT `datetime` from there on out. – abarnert Mar 22 '13 at 23:49
  • @abarnert: Oh, slick, I'll give that a go and report back.... – Garfonzo Mar 22 '13 at 23:49

1 Answers1

2

The best solution here is probably to have your jQuery code convert its datetimes to GMT before sending them. (If you want the timezone as well, send it separately.) Then you can get them out of the JSON (or whatever) on the Python side, turn them into GMT datetime objects with strptime, and use them, and you're done.

But the simplest solution,* with the least code change, is to just let jQuery do the wrong thing and throw away the timezone on the Python side. Basically, instead of this:

dt = datetime.datetime.strptime(jsondate)

do this:

dt = datetime.datetime.strptime(jsondate.partition('(')[0])

Notice that throwing away everything after the '(' still leaves you with the -0600 part; you're just losing the "PST" or "Mountain Daylight Time" part.

And those parts were not doing you any good anyway. datetime doesn't understand these timezone names. And, even if it did, it has nothing to map them to except for offsets (which you already have). If you want real timezones, you need some third-party library like pytz.**

On top of that, strptime specifically returns naive datetime objects, not aware ones. So, even if datetime could parse and look up the timezones, it still wouldn't do anything useful with them, unless you parsed the datetime, then pulled out the timezone and parsed it separately and looked it up and then called astimezon on the datetime.

So, in summary, the worst-case scenario for throwing this information away is exactly what you already have.

As a side note, on three projects in a row, I pushed a datetime serializer into my JSON en/decoder on the Python side (and a matching serializer on the JS side, for the one that had a JS side) specifically so I could pass a UTC datetime (in ISO8601 format, because that's as easy to use for computers as a seconds-since-epoch, and a lot easier to read/edit for humans) and a timezone offset today, but switch to a tzinfo key if it because important later. All three times, it never became important… And the projects where it has been important, I've usually been passing around ICAL schedules or pre-Gregorian dates or other similarly fun stuff.

Finally, as someone who's written way too much date-related code over my career, I have to say this: If you know of any evil overlords planning to take over the world, if they promise to abolish timezones, I am willing to overlook their other programs of enslaving humanity or making kittens fight babies and sign up as a henchman.

* … at least simplest for me, since I know Python a lot better than JS and jQuery. :)

** IIRC, pytz can't handle NT-style timezone keys like "Mountain Daylight Time" either, so you actually need yet another library to handle that. I think I got that out of a library that did all kinds of MS datetime stuff, including handling the differences between Microsoft's three similar 1601-ish epoch times (two not-quite-the-same epochs, different rules for special "end of time" and "start of time" and "not a date" values, …).

abarnert
  • 354,177
  • 51
  • 601
  • 671