Python - date object from Windows machine -- time zone issues - javascript

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?

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, …).

Related

Node 8 vs 11 Timezone is different

Running a simple new Date().toString(). On Node 11, You get something like
'Fri May 10 2019 10:44:44 GMT-0700 (Pacific Daylight Time)'
While on Node 8 you get
'Fri May 10 2019 10:44:44 GMT-0700 (PDT)'
Note the different in timezone abbreviation. Why is that? And how can you force toString() to always return the zone in the abbreviation?
Stolen answer from #ssube who was too lazy to log in and post.
the whole Intl object and default formats were introduced between those two versions, which may have become the new default for Date as well.
After some digging on my own, and reading some of the Intl spec:
The ECMAScript 2015 Internationalization API Specification identifies time zones using the Zone and Link names of the IANA Time Zone Database. Their canonical form is the corresponding Zone name in the casing used in the IANA Time Zone Database.
As to how to revert back to an abbreviated timezone, I am seeing that there are several github repos that suggest using regex, others using an abbreviation Map, or even Ben Nadel who uses some regex to process the short timezone or long timezone, as seen in his blog here
Looks like JavaScript leaves this up to the implementer. Based on the below GitHub Issue for ECMA262, there are known differences between the ways UNIX & Windows handle the timezone value.
Across multiple JS implementations, it seems that Date.prototype.toString writes the timezone (in parens) in a long, locale-dependent form on Windows, but in a short form (2-4 letters) from the tz database on Unix-based OSes. More details in the V8 bug tracker.
The spec is really light on details for Date.prototype.toString:
Return an implementation-dependent String value that represents tv as a date and time in the current time zone using a convenient, human-readable form.
Does anyone have a good memory of why this is the definition? Looks like it goes all the way back to ES1.
Fortunately, it seems that, at this point, implementations have converged on something that's almost always the same, with the exception of the timezone string.
For the timezone string, would it be a good idea to pick one of the two alternatives and standardize it across all platforms? Does anyone have evidence one way or the other whether either of the two is likely to be more web-compatible, or whether we need to preserve the variation?
Additionally, it looks like there is still active discussion in the V8 Issues for Date.prototype.toString() normalization.
Going through the NodeJS there doesn't seem to be an explicit mention of this in their change logs for v10+.
Update
After digging through V8 commits, it looks like there is a new Timezone Names Cache implemented for performance in V8 when using Date.prototype.toString(). Based on the below excerpt from the message for this commit, it seems like this change is why there is a difference between Node v8 & Node v11
To speed up Date.prototype.toString(), this patch adds a cache in the
DateCache for the string short name representing the time zone.
Because time zones in a particular location just have two short names
(for DST and standard time), and the DateCache already understands
whether a time is in DST or not, it is possible to keep the result of
OS::LocalTimezone around and select between the two based on whether
the time is DST or not.
In local microbenchmarks (calling Date.prototype.toString() in a
loop), I observed a 6-10% speedup with this patch. In the browser, the
speedup may be even greater as the system call needs to do some extra
work to break out of the sandbox. I don't think the microbenchmark is
extremely unrealistic; in any real program which calls
Date.prototype.toString() multiple times, the cache should hit almost
all of the time, as time zone changes are rare.
The proximate motivation for this patch was to enable ICU as a backend
for timezone information, which is drafted at
https://codereview.chromium.org/2724373002/ The ICU implementation of
OS::LocalTimezone is even slower than the system call one, but this
patch makes their performance indistinguishable on the microbenchmark.
In the tz database, many timezones actually do have a number of
different historical names. For example, America/Anchorage went
through a number of changes, from AST to AHST to YST to AKST. However,
both ICU and the Linux OS interfaces just report the modern timezone
name in tests for the appropriate timezone name, even for historical
times. I can see why this would be:
- For ICU, CLDR only has two short names in the data file: the one for dst and non-dst
- For Linux, the timezone names do seem to make it into the /etc/localtime file. However, glibc assumes there are only two
relevant names and selects between them, as you can see in its
implementation of localtime_r:
http://bazaar.launchpad.net/~vcs-imports/glibc/master/view/head:/time/tzset.c#L573
So, this cache should be valid until we switch to a more accurate
source of short timezone names.

Time zone issue when using REST Api and JS

I'm using FormatJS library along with Handlebars to display a list of events that occured in the past. I'm calling for an endpoint on my server's REST API which returns me the list of events in Json, with datetimes to display for each event. ATM I'm saving datetimes in the DB using GMT time zone.
So when I'm getting my Json, I'm handling datetimes like this :
{{formatRelative commentDate}}
My issue is, since the datetimes are stocked in GMT, they display also like that. For example, since I'm on a GMT+2 timezone, as soon as a new event is created and shows up on the list, I see it "happened 2 hours ago" while it should be "a few seconds ago".
So, is there a way I can handle this ? Am I making a mistake in saving datetimes in GMT in my DB, and if so, how would you handle datetimes coming from different timezones and displaying them to people in other timezones ?
Of course I could customize the formatRelative helper to play with getTimezoneOffset and get the wanted result, but I wanted to know if there is something better to do.
Thanks a lot ahead !
The key to understanding your question is what you wrote in the comments:
Getting the Json, containing datetimes in the format 2016-02-28 10:15:53 - that's UTC time
You should ensure the value in JSON is in full ISO8601 format, including the appropriate offset or Z character to indicate UTC: 2016-02-28T10:15:53Z
Without the offset, most implementations will consider the value to be represented in local time, which explains your results.
Thus, the problem is with your server-side code, not your JavaScript code. There may be a client-side workaround you could apply when the date string is parsed from JSON, but really the best solution would be to qualify it at the server.

Java and JavaScript timestamps are not the same

I've got a problem with timestamps between java and javascript.
I already found these 2 questions about the timestamps and I know about the timechanges all over the years.
Timestamp deviation Java vs Javascript for old dates (3600secs)
Why is subtracting these two times (in 1927) giving a strange result?
Basically at midnight at the end of 1927, the clocks went back 5
minutes and 52 seconds. So "1927-12-31 23:54:08" actually happened
twice, and it looks like Java is parsing it as the later possible
instant for that local date/time.
What the problems makes is that when I have javascript and put the timestamp in there then I get an other date than the Java date. I need this to show the correct date on the webpage. I know I can request the date as a string but I prefer using a timestamp.
Java date 0001-01-01 timestamp is -62135773200000
JavaScript date 0001-01-01 timestamp is -62135596800000
The difference is -176400000; 49 hours.
Does anybody know what I can do for this.
Personally, I would avoid passing numerical timestamps around from a system in one language to a system in another language for the sole reason that the languages may differ in the algorithm they use to generate them.
There is an international standard in place (ISO-8601) to deal with passing timestamps from system to system. In this your date representation becomes 0001-01-01T00:00:00+00:00. I would recommend using this approach, as it's a widely accepted solution for this very problem.
This might be related to TZ and DST settings which diverge from browser to java. In order to nail it down, I recommend to use ISO-8601 formats like 2008-02-01T09:00:22+05, this is ambiguous-less

javascript dateTime - the same format as server

I have an ajax call, which returns datetime. Javascript displays it using client timezone. I not need in any client timezone, I want to show datetime the same as server return. Is it possible?
I get date via:
var d = eval('new' + date.replace(/\//g, ' '));
First off, there's no reason to use eval here (or almost anywhere), and generally lots of reasons not to.
JavaScript has only "local" time (the timezone of the client) and UTC (universal coordinated time, effectively the same as GMT). So your best bet normally is to have the server send you the time in UTC. But in your case, since you want to display the date in the server's timezone, it doesn't really matter whether JavaScript thinks the date is in local time or server time, and it's fine to send it in the server's timezone.
Note that when parsing date strings, JavaScript only recently (as of ECMAScript5) got a standard format for date strings, which is a simplified version of ISO-8601. Details here. Note that some older browsers will not yet support that format.
It's impossible to offer much more guidance without an example of what you're trying to parse.
Diodeus' suggestion also seems to me to make a lot of sense: If you want the date to be displayed in the server's timezone and format, just display the string you're given without interpreting it (again, subject to what the string looks like; I can't immediately come up with a reasonable format that would work with your posted code).

Javascript date object in different locale and timezone

I need to write a web application that show events of people in different locale. I almost finished it, but there're 2 problems with date:
using date javascript object, the date depends on user computer settings and it's not reliable
if there's an event in a place with dfferent timezone respect user current position, i have to print it inside (). Is it possible in javascript to build a date object with a given timezone and daylight settings?
I also find some workaround, such as jsdate and date webservices, but they don't overcome the problem of having a javascript object with the correct timezone and daylight settings (for date operation such as adding days and so on).
A couple of things to keep in mind.
Store all event datetimes in UTC time
Yes, there is no getting around this.
Find out all the timezones...
...of all the users in the system. You can use the following detection script: http://site.pageloom.com/automatic-timezone-detection-with-javascript. It will hand you a timezone key such as for example "America/Phoenix".
In your case you need to store the timezone together with the event, since a user may switch timezone - but the event will always have happened in a specific one. (argh)
Choose your display mechanism
If you want to localize your event dates with Javascript, there is a nifty library for that too (which can use the keys supplied with the previous script). Here: https://github.com/mde/timezone-js.
with that library you can for example do this:
var dt = new timezoneJS.Date(UTC_TIMESTAMP, 'America/New_York');
or
var dt = new timezoneJS.Date(2006, 9, 29, 1, 59, 'America/Los_Angeles');
where UTC_TIMESTAMP for example could be 1193855400000. And America/New_Yorkis the timezone you have detected when the event took place.
The dt object that you get from this will behave as a normal JavaScript Date object. But will automatically "correct" itself to the timezone you have specified (including DST).
If you want to, you can do all the corrections in the backend - before you serve the page. Since I don't know what programming language you are using there, I cannot give you any immediate tips. But basically it follows the same logic, if you know the timezone, and the UTC datetime -> you can localize the datetime. All programming languages have libraries for that.
You're missing the point of a Date object. It represents a particular point in time. As I speak, it is 1308150623182 all over the world. Timezone only comes into play when you want to display the time to the user. An operation like "adding a day" does not involve the time zone at all.
One possibility might be to use UTC date and time for everything. That way, there is nothing to convert.
Another is to have your server provide the time and date. Then you don't have to depend on the user to have it set correctly, and you don't have to worry about where your user's timezone is.
Use getUTCDate(), getUTCHours(), ... instead of getDate(), getHours(),...
getTimetoneOffset() could be useful, too.

Categories