JavaScript: How to set a date so that it looks the same all over the world? - javascript

One of our programmers decided to use a DATE field in the MySQL db in order to achieve this.
Sending and saving a JS date object did work well until the daylight saving changes intervened (with nasty effects :) ).
Of course, saving the date in a DATETIME field solves it, but everybody sees the time/dates in their own timezone.
We need everybody (all over the timezones) to see the same date!
I clarify this, to get the proper answers:
I want to keep using the DATE field storage type in MySQL (vs DATETIME - ok, maybe too much of an optimization, but it's already there and I want a long term solution for when I receive such structure/code from other developers)
Sending local time (local JS in browser) 23-05-2016, will reach the server as 22-05-2016 0X:X0:00Z (UTC) and be store as such. Because it's a DATE field, the stored value will become 22-05-2016 only. And you lost a day! :)
Our solution from bellow not only fixes the DATE field trimming, but also adds the fact that people now can see the same correct date (23-05-2016) no matter of the timezone they are in!
I like the outcome and would love to see some better solutions to achieve the same and improve the system.
Actually, we have noticed the problem only when the daylight saving time changed, so my solution (as answer bellow) is a good solution for that as well. And it only consumes resources client-side.
I have posted my own solution to this question as an answer bellow.
It would be really cool to see a much better solution from you!

With Javascript
Save your dates in ISO format (including timezone information) and use moment.js to convert the datetime to another timezone.
If moment.js is not already a dependency, and you want to avoid extra libraries, keep reading.
With MySQL
Instead of solving this problem when you write the data (losing timezone information in the process), solve it when you read the database.
In your SELECT query, normalize all DATETIME values to your preferred timezone using the convert_tz built-in function.

MomentJs is your best bet. Find the timezone you want and pass the ISO string to it and you should be good to go.
http://momentjs.com/timezone/docs/#/using-timezones/

A DATE is just a year, month, and day. It doesn't have a time, or a time zone. Think about your birthday or your wedding date, or today's date.
The JS Date object is not this at all. It's a timestamp. It's the number of milliseconds elapsed since Midnight January 1st 1970 UTC.
You should leave your date as a date-only wherever possible. Use the ISO-8601 date-only format, which is YYYY-MM-DD. If you have to assign it a time and time zone, then be very careful when you do.
If you just assign midnight local time, then you're risking losing a day (as you showed), and you're not considering that there are local days in some time zones where midnight does not exist! (Such as the spring-forward day in Brazil). Noon is a safer bet than Midnight, but still you should use this sparingly. The better approach is to keep dates as dates, not as date-times.
Also, I'd answer with code if I could, but you didn't provide any code in your question showing what was broken. Please read How do I ask a good question? and How to create a Minimal, Complete, and Verifiable example. Thanks.

There are more solutions to this, but the fastest and easiest that I could come up with is described bellow:
Let's intervene as early as possible in the information stream.
Just change the data before transmitting it through AJAX.
The function we used is this:
function addTimezoneDiffAnd12HoursToDate(date) {
var timezoneOffset = date.getTimezoneOffset();
date.setHours(12-Math.floor(timezoneOffset/60));
date.setMinutes(-timezoneOffset % 60);
return date;
}
What it does is that it converts a Date to be always at noon (12:00) UTC!
You can use it like this:
$scope.contract.contractDate = addTimezoneDiffAnd12HoursToDate($scope.contract.contractDate);
and send it as such to be stored in the DATE field.
Let me know if you have a simpler solution. I'd like to see it.

Related

Get UTC offset from timezone abbreviations

Is there anyway to get utc offset from a timezone abbreviations? Such as:
"PST"
for
Pacific Standard Time (North America)
which will result in UTC−08. I found a way on moment-timezone but it did not help much.
It provides a list of timezone identifier but most of them are deprecated.
Thank you.
This is a quite tricky topic and similar questions have already been discussed.
See Detect timezone abbreviation using JavaScript or
Get timezone abbreviation using offset value
I would propose two options:
1. Hash table. Create a key-value pair of what you require based on standard information (e.g. list of timezone abbreviations and their offset). Something like
let offsetByAbbrev = {"PST" : "UTC-08", "EST" : "UTC+01", ... }
But this needs serious maintenance as it will get deprecated quickly.
2. Date manipulation. You can create a date in a specific timezone with momentjs, however, not with abbreviations. And there is a good reason for it: these abbreviations can change and can also cause ambiguity. You can check out the JSON used by momentjs-timezone: https://github.com/moment/moment-timezone/blob/develop/data/packed/latest.json which will give you a general sense of how chaotic it can be. For example do a simple ctrl+f search for PST and see the results.
So I would suggest using the timezone names - which you can actually create and use with momentjs-timezone. See How to create time in a specific time zone with moment.js where you can create a moment object based on the timezone name and that object will contain (as per the spec of moment timezone: https://momentjs.com/timezone/docs/#/zone-object/) the offset itself.
I know this does not exactly resolve your problem, though what you are trying to do is not necessarily the best approach to reach your an ideal solution.

Should I use `Date()` to store a date without time in javascript

I need to store in the backend a date in the format yyyy-mm-dd;
I've initially used in the frontend a js Date() object to store it, and dropping the time and timezone info while sending it to the backend; but that caused a "timezone issue" when parsing back the yyyy-mm-dd string into Date();
even if it's possible to workaround that issue I was wondering if using a simple String wouldn't be better; is there any drawback that now I cannot see and so I should use a Date anyway?
Similar to other comments, I would also recommend sticking with Date instead of strings to prevent browser differences and for ease of use. One note is when setting the date, don't forget to account for day-light savings which might cause a database crash if not accounted for.
CSS-Tricks: Everything you need to know about date in javascript

Does momentjs have something similar to joda-time's localDate? If not, is it best to use .startOf?

In the joda-time library (and I assume Java 8's new time library), you can ignore times and time zones: https://www.joda.org/joda-time/apidocs/org/joda/time/LocalDate.html
I would prefer to avoid having times factor in in my small app. I just want the user to see their local date. Is there a momentjs equivalent to localdate? If not, would the best workaround be to use .startOf()? Thanks.
Edit: Just to be clear, this is not a formatting question.
"By default, moment parses and displays in local time.
If you want to parse or display a moment in UTC, you can use moment.utc()"
As explained here.
moment().format(); // 2013-02-04T10:35:24-08:00 (local date)
moment.utc().format(); // 2013-02-04T18:35:24+00:00 (UTC date)

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.

How to find browser date time format [duplicate]

I have set a deadline in UTC, as shown below, and I'm wondering what exactly the toLocaleString() method will do to it on user's local machines. For instance, will it account for daylight savings if they are in a timezone that recognizes it? Or will I need to insert additional code that checks where the user is, and then fixes the displayed time?
http://javascript.about.com/library/bldst.htm
var deadline = new Date('5/1/2013 ' + "16:15" + ' UTC');
alert(deadline.toLocaleString());
In general, the answer is yes. JavaScript will represent the UTC value at the appropriate local time based on the time zone settings of the computer it is running on. This includes adjustment for DST. However, as others have pointed out, the details are implementation specific.
If you want a consistent output, I would use a library to format your dates instead of relying on the default implementation. The best library (IMHO) for this is moment.js. The live examples on their main page will give you an idea of what it can do.
UPDATE
If you are passing UTC values that you want converted to the correct local time, and that time falls into a period where the time zone rules are different than the current one - then the results will be invalid. This is crazy, but true - and by design in the ECMA spec. Read - JavaScript Time Zone is wrong for past Daylight Saving Time transition rules
We don't know what exactly the toLocaleString method does (§15.9.5.5):
This function returns a String value. The contents of the String are
implementation-dependent, but are intended to represent the Date in
the current time zone in a convenient, human-readable form that
corresponds to the conventions of the host environment’s current
locale.
But yes, most implementations will consider DST if it is active in the current local timezone. For your example I'm getting "Mittwoch, 1. Mai 2013 18:15:00" - CEST.
Will I need to insert additional code that checks where the user is, and then fixes the displayed time?
I think you can trust toLocaleString - the browser should respect the user's settings. If you want to do it manually, check out timezone.js.
As you use "UTC" the date itself will be UTC format, but the toLocaleString() takes client's locale into account, which means it'll return the date in string updated with all and every changes typical to client's regional and locale settings (DST, date/time format, etc).As JS documentation describes this: "The toLocaleString() method converts a Date object to a string, using locale settings.".If you want to avoid this, use the toUTCString() method instead.I'd also recommend reading the accepted solution for the question Javascript dates: what is the best way to deal with Daylight Savings Time? to avoid (at least, to try to avoid :) future issues related to JS, browsers and locales.Hope this helps!

Categories