My app runs on Linux servers, where the time is (naturally) set to UTC/GMT. However the app is developed on Mac desktops where the time is typically set to a local timezone.
I could change every new Date() in my code to run:
var date = new Date().getTime();
And thus ensure dates on the server are always GMT, but that seems inelegant.
I understand previous versions of node used to always return UTC/GMT. Is there any way to bring this behavior back?
Edit: Removed adding timezone offset to getTime() per comments - since getTime() is already in UTC.
You can use TZ configuration parameter of node.js as follows.
For bash (and related)
export TZ=UTC
For Powershell
$env:TC = 'UTC'
Then for both:
nodejs server/index.js
From the MDN docs on Date#getTime:
The value returned by the getTime method is the number of milliseconds since 1 January 1970 00:00:00 UTC.
Assuming you're storing dates/times as numbers (which I would recommend), getTime is already UTC, always.
Suppose your client then requests a date from the server. If the server provides the date as a number, the client can then do:
new Date(timestamp);
And it will be correctly adjusted to the local time on the client.
Of course, maybe I'm misunderstanding your problem. But I just want to point out that this...
new Date().getTime() + new Date().getTimezoneOffset();
...should never really make sense. It's taking a UTC-based time and then offsetting it further, in essence double-offsetting a time.
Related
I wanted to know if a date object created at any point of time differ based on time zones or not. I tried this by executing new Date().getTime() once for IST and immediately again by setting my PC time zone to GMT. The resultant values are:
IST - 1633334780053
GMT - 1633334788831
A difference of around 8000 milliseconds
From this it seems that datetime objects created at same moment are exactly same no matter in which time zone they are created. Please suggest if this understanding is correct or is there more to it.
You're right. Two different date time objects created at the same point of time are same no matter the time zone.
They can be formatted to their corresponding timezone representation using javascript.
One important thing to be noted is that the date time object created uses the system's date time configuration to find the correct time. If the system's date and time configurations are correct and in sync, then the date time object created in the browser will be correct and will match the system time at the time of creating that object.
This is detailed in the JavaScript specification: https://tc39.es/ecma262/#sec-date-objects.
More information is in the MDN docs Date.getTime():
The getTime() method returns the number of milliseconds* since the Unix Epoch.
*JavaScript uses milliseconds as the unit of measurement, whereas Unix Time is in seconds.
getTime() always uses UTC for time representation. For example, a client browser in one timezone, getTime() will be the same as a client browser in any other timezone.
So new Date().getTime() will always return the number of milliseconds since 1970-01-01 00:00:00 UTC, regardless of the client / machine timezone setting.
I want to display the local date of the user, but nothing is working for me. It always returns the UTC time.
I have tried:
This returns UTC - also in here offset comes as zero.
let visitDate = moment.utc().format();
let offset = moment().utcOffset();
let visitDate1 = moment.utc(visitDate).utcOffset(offset)
This returns UTC
let visitDate = new Date()
let visitDate1 = moment(visitDate).local().format('MM-DD-YYYY hh:mm:ss');
This returns UTC
let visitDate = new Date()
let visitDate1 = visitDate.toLocaleDateString()
I have tried several methods, but it doesn't matter what I do, I always get UTC time. If I try on localhost then it displays the correct time, but once I host the page it displays UTC.
How can I transform to local?
moment().local() uses the timezone of the local machine, that's why it works in localhost
if you know it, I would specify the timezone:
moment.tz("America/Los_Angeles").format()
There seem to be several possible points of failure. I'll list the ones I think of below, and you can assess whether they're relevant to your setup.
1) The code that manipulates the date is executed on the server, not locally
Most of our Javascript code is written to execute in the user's browser, so that's the default assumption. If that assumption is wrong in this case, and the code is being executed on the server, then "local" means "on the server." Your server should be running with UTC time, which could produce the results you're seeing.
2) The user is running a browser set to UTC
If the browser you're using for testing is set to consider UTC as local time, it'd produce the results you're seeing. Since you're probably using the same machine for localhost and for testing, it's an unlikely source of the problem...but worth noting nonetheless.
3) Changing how the date is displayed does not change how the date is stored
Many of the tools we have for setting/changing the time zone affect how the date is displayed. However, Date objects in Javascript are stored using Unix Time (in milliseconds), which is UTC. When you create a Date object--even with a time zone specified--the behind-the-scenes representation will still be an integer (representing a number of milliseconds) and based on UTC. If you're checking the stored value rather than the displayed value, when you're testing, then there's a good chance you'll always see UTC. However, the work you're doing with the moment library should have the date formatted correctly. If you're checking the moment object, you should be seeing the time zone you expect to see.
If none of these three possible failure points applies to your context, then perhaps they spark an idea for you. (The third one, especially, feels like it might be on the right track even if it's not what's happening in your case.)
I am using new Date(<date-string>) and then .getTime() to pass date strings to milliseconds from 1970.
The problem is that the date strings does not contain the timezone on them. They are British, so the timezone will be GMT or GMT+1 depending on the date...
When I use this technique in the front-end (Chrome), or in the back-end (Node.js). The time zone taken is the British one (GMT or GMT+1 depending on the date). I assume that is taken from the OS.
However, when using a Node.js server which I have been told is configured to be in UTC... the timezone is always going to be GMT, leading to errors during the British Summer Time.
Is there any way to tell Date to take the timezone from the OS without changing the server configuration?
Example:
var aDate = new Date('2016-06-23 10:15:0');
var timestamp = aDate.getTime();
Just in case my explanation is not clear:
// Executed on 28-06-2016
// In the browser (in London)
new Date().getTimezoneOffset(); // -60
new Date('28-06-2016 11:11:11').getTimezoneOffset(); // -60
new Date('28-01-2016 11:11:11').getTimezoneOffset(); // 0
// In the Node.js server I am forced to use, which is configured to use UTC
new Date().getTimezoneOffset(); // 0
new Date('28-06-2016 11:11:11').getTimezoneOffset(); // 0
new Date('28-01-2016 11:11:11').getTimezoneOffset(); // 0
// Ideally, I would like to have the output I get in the browser when I run the code in the UTC Node.js server
I recommend using Moment Timezone for this, since this would be needlessly complicated to implement without a library. To get UTC in milliseconds from a given date in a given timezone, you can do this:
const moment = require('moment-timezone');
function londonTimeToUTC(dateString) {
return moment.tz(dateString, 'DD-MM-YYYY HH:mm:ss', 'Europe/London').valueOf();
}
console.log(londonTimeToUTC('28-06-2016 11:11:11')); // 1467108671000
console.log(londonTimeToUTC('28-01-2016 11:11:11')); // 1453979471000
The second argument passed to moment.tz() is a format string, which is necessary if the date string is not in ISO format. The third argument is any valid timezone identifier.
Is there any way to tell Date to take the timezone from the OS without changing the server configuration?
The time zone from the OS is what the Date object uses. If you're asking if you can change that time zone without changing the configuration, then no - there is not a way to do that. The Date object always takes on the behavior of the local time zone. Even if you supply an offset in the input string, it just uses that to determine the internal UTC timestamp. Output via most of the properties (including toString and getTimezoneOffset) will always use the local time zone.
Even in your examples, you cannot count on the browser behavior always returning the values you showed, simply because each user visiting your web site may have a different time zone setting.
The recommended way to deal with this is by using the moment.js library, which can handle UTC and local time by itself, but may require use of the moment-timezone extension if you are wanting to work with a specific time zone, such as Europe/London.
Now, with that said, if you're certain that your entire node.js application will run in a single time zone, and you're running on Linux or OSX (not Windows), then you can indeed change which time zone that node.js considers to be "local". Simply set the TZ environment variable before you launch node, like this:
env TZ='Europe/London' node server.js
There is no equivalent for the browser, or for Windows. And you still have to contend with possible non-UK users on your web site - so this doesn't guaranteed a match between client and server time. But it does address your question.
See also:
How to initialize javascript date to a particular timezone
How to make the timezone of date to UTC
How to set default timezone in Node.js
My app is based on XULRUNNER. I found when I fetch the current timestamp with Date.prototype.getTime, It seems give me the GMT time not the time of my time zone. But in firefox, there is no such a problem. I am confused that is there a way to set the time zone in xulrunner with JS.
Date.prototype.getTime doesn't really have a notion of UTC or timezone, it's a number of milliseconds elapsed since a specific point in time, the Unix EPOCH, which happens to be defined in UTC. If you convert it to a date manually, you will always get a value seemingly in UTC, in XULRunner or Firefox.
You need to use the other methods on Date objects to retrieve the time in the local timezone.
var now = new Date();
console.log(now.getTime()); // 1390141979617
console.log(now.getUTCHours()); // 14
console.log(now.getHours()); // 9
Compare the results of toString() and toLocaleString()
I typed "date" in console...and I get Tue Sep 20 01:01:49 PDT 2011 ...which is correct.
But then I do this in node.js, and I get the wrong time.
var ts = String(Math.round(new Date().getTime() / 1000));
Output is: 1316505706, which is an hour behind.
#KARASZI is absolutely correct about the root cause: Unix timestamps are always UTC unless you manipulate them. I would suggest that if you want a Unix timestamp you should leave it in UTC, and only convert to local time if you need to display a formatted time to the user.
The first benefit of doing this is that all your servers can "speak" the same time. For instance, if you've deployed servers to Amazon EC2 US East and Amazon EC2 US West and they share a common database, you can use UTC timestamps in your database and on your servers without worrying about timezone conversions every time. This is a great reason to use UTC timestamps, but it might not apply to you.
The second benefit of this is that you can measure things in terms of elapsed time without having to worry about daylight savings time (or timezones either, in case you're measuring time on a platform which is moving!). This doesn't come up very much, but if you had a situation where something took negative time because the local time "fell back" an hour while you were measuring, you'd be very confused!
The third reason I can think of is very minor, but some performance geeks would really appreciate it: you can get the raw UTC timestamp without allocating a new Date object each time, by using the Date class's "now" function.
var ts = Date.now() / 1000;
The reason is that the getTime function returns the time in the UTC timezone:
The value returned by the getTime method is the number of milliseconds since 1 January 1970 00:00:00 UTC. You can use this method to help assign a date and time to another Date object.
If you want to fetch the UNIX timestamp in you current timezone, you can use the getTimezoneOffset method:
var date = new Date();
var ts = String(Math.round(date.getTime() / 1000) + date.getTimezoneOffset() * 60);
Note you can avoid this confusion by using a node.js package like timezonecomplete or timezone-js which have an interface that is much less error-prone for date and time manipulation.
date in console will return the server time, whereas using JavaScript on a webpage will return the client's local time.