I. new Date()
Reportedly there are 4 ways:
new Date();
new Date(value);
new Date(dateString);
new Date(year, month[, day[, hour[, minutes[, seconds[, milliseconds]]]]]);
The 1st way is used to get timestamp:
// get ts
var now = Date.now || function() {
return new Date().getTime();
};
The 2nd way converts timestamp to Date object:
// ts to Date
var ts2Date = function(ts) {
return new Date(ts);
};
The 3rd way converts date time string to Date object:
// string to Date
// eg. '2016/10/01 12:01:02'
// '2016/10/01'
var str2Date = function(str) {
return new Date(str);
};
The 4th way is generally not used, because the 4th way has a very uncomfortable problem (month is 0-11):
// set Date
// eg. 2016, 9, 1, 12, 1, 2
// 2016, 9, 1
var setDate = function(y, m, d, h, mm, s, ms) {
return new Date(y, m, d, h, mm, s, ms);
};
// in getter/setter, month is 0-11
var date = new Date(); // Today is 2016-10-01
date.getMonth(); // 9
date.setMonth(10);
date.toString(); // Tue Nov 01 2016 11:46:58 GMT+0800 (China Standard Time)
The 4th method internally may use setter, so month starts from 0
The 3rd way is more useful, because generally date strings that need processing are ISO standard format, like 2016-10-01 12:01:02, but this is non-standard in JS
II. Date Time String Format
Non-Standard Format
First look at these two things:
// new a zone 0 time
new Date('2016-10-01'); // Sat Oct 01 2016 08:00:00 GMT+0800 (China Standard Time)
// new a current timezone time
new Date('2016/10/01'); // Sat Oct 01 2016 00:00:00 GMT+0800 (China Standard Time)
The second is correct, the first has extra 8 hours, browser thinks the first input is zone 0 time, privately adds 8 hours for East 8 zone users, equivalent to:
// Sat Oct 01 2016 08:00:00 GMT+0800 (China Standard Time)
new Date('01 October, 2016 GMT+0000');
// Sat Oct 01 2016 00:00:00 GMT+0800 (China Standard Time)
new Date('01 October, 2016 GMT+0800');
So never use yyyy-MM-dd, even if very sure want to new a zone 0 time, shouldn't do this, because others may not understand, if really want to new a zone 0 time, should use its equivalent format (with GMT timezone标识)
Add time 'HH:mm:ss' and try again:
// new a zone 0 time
// Sat Oct 01 2016 12:01:02 GMT+0800 (China Standard Time)
new Date('2016-10-01 12:01:02');
// new a current timezone time
// Sat Oct 01 2016 12:01:02 GMT+0800 (China Standard Time)
new Date('2016/10/01 12:01:02');
Surprisingly consistent, but Safari (including IOS Safari) doesn't support yyyy-MM-dd HH:mm:ss format, Safari from beginning to now (2016-10-01) doesn't support this format, because it's non-standard, probably doesn't intend to support
Although yyyy/MM/dd HH:mm:ss is also non-standard, but because of long history, all browsers including IE6 support this format
So, there are two widely supported non-standard formats:
// eg. 2016/10/01 12:01:02
yyyy/MM/dd HH:mm:ss
// eg. 01 October, 2016 12:01:02 GMT+0800
week, dd month yyyy HH:mm:ss GMT±HHmm
The former defaults to current timezone time, the latter can set timezone
Standard Format
Until ES5.1 15.9.1.15 Date Time String Format there was a format standard for date strings:
// zone 0 time
YYYY-MM-DDTHH:mm:ss.sssZ
// east side time
YYYY-MM-DDTHH:mm:ss.sss+HH:mm
// west side time
YYYY-MM-DDTHH:mm:ss.sss-HH:mm
This specification is from June 2011, so compatibility can be imagined, looks quite strange, but standard-abiding Safari supports it, for example:
// zone 0 time
// Sat Oct 01 2016 20:01:02 GMT+0800 (CST)
new Date('2016-10-01T12:01:02Z')
// East 8 zone time
// Sat Oct 01 2016 12:01:02 GMT+0800 (CST)
new Date('2016-10-01T12:01:02+08:00')
Similarly, zone 0 time will still be privately added with timezone offset, then easily think of these two:
new Date('2016-10-01T12:01:02+00:00')
new Date('2016-10-01T12:01:02-00:00')
They are all equivalent to Z, will also be localized offset
III. GMT vs UTC
Generally can consider these two things the same, both represent world standard time, and Beijing is in East 8 zone, so:
// Generally can consider
Beijing Time === UTC+8 === GMT+8
UTC and GMT are consistent in timezone concept, but UTC emphasizes precision, smaller error, this error is relative to UT
GMT
GMT (Greenwich Mean Time) is the earliest defined world time. In 1884, representatives from various countries went to Washington for a meeting, reached consensus on timezones, with prime meridian as center (located in zone 0), east 1 to 11 zones, west 1 to 11 zones, sharing 12 zone (called "East West 12 Zone"), total 24 timezones
Zone 0 publishes standard time, then other zones add corresponding offset to get local time
UT
UT (Universal Time) is time calculated based on celestial observation. UT itself is a broad concept, including UT0, UT1, UT2, etc. Among them UT0 is time completely calculated according to celestial operation, UT1 is made some adjustments based on UT0, UT2 is made further adjustments based on UT0 and UT1. Due to some uncertainties in celestial operation (for example Earth's rotation is not uniform, but accelerates and decelerates in complex ways), so UT time doesn't flow uniformly.
UT is theoretically "correct" time
UTC
UTC (Universal Time Coordinate) is time based on atomic clock. What is atomic clock? Personally think it's a very small, fixed length, indivisible time segment. So UTC time is uniform. To minimize error with UT time as much as possible, UTC introduces leap seconds (in certain years the last minute is 61 seconds), to ensure error between UTC and UT1 is within 0.9 seconds.
UTC accepts GMT's timezone concept, so UTC is equivalent to giving GMT a more advanced watch, what watch GMT uses is unknown
IV. Potential Problems
The biggest difference from Beijing time is West 12 zone (only a few small islands):
deltaH = (+8) - (-12) = 20
If made a local time judgment, for example:
if (new Date() > new Date('2016/10/02')) {
alert('a new day');
}
Then users in different timezones will all see a new day when their device shows October 2, 2016 0:00 non-zero milliseconds, this is no problem, but if scenario is like this:
if (new Date() > new Date('2016/10/02')) {
alert('Exam time arrived, return to homepage after 3 seconds');
setTimeout(function() {
location.href = '/index.html';
}, 3000);
}
Then the problem is big, Beijing time October 2, 2016 0:00 non-zero milliseconds, exam status changes to CLOSED, no longer accepts submissions, then users in other timezones find the problem:
-
Friends living in West 12 zone still have 20 hours to slowly answer questions, find out when submitting that they're not wanted
-
Friends living in East 12 zone are worse off, exam collected 4 hours early
Of course, we generally ask server for status first when entering page, based on server time, because local time is unreliable (users can casually modify device time), another reason is mentioned above: timezone differences will make users in other timezones very confused
So, even if must use local time judgment, should do it like this:
if (new Date() > new Date('02 October, 2016 GMT+0800')) {
alert('Exam time arrived, return to homepage after 3 seconds');
setTimeout(function() {
location.href = '/index.html';
}, 3000);
}
Compare user's local time with Beijing time, at least under user device time, can guarantee consistent status. Of course, problem of manually changing time cannot be avoided (for example some farm games in the past used local time), so try not to use local time as judgment basis
V. Summary
Local time refers to device's timezone time
Best compatibility time string format:
// doesn't support timezone
2016/10/01 12:01:02
yyyy/MM/dd HH:mm:ss
// supports timezone
new Date('01 October, 2016 GMT+0800')
week, dd month yyyy HH:mm:ss GMT±HHmm
ES5.1 standard time string format:
2016-10-01T12:01:02+08:00
YYYY-MM-DDTHH:mm:ss.sss±HH:mm
Time string formats to never use:
// compatibility no problem, but will be forcibly offset, for example +8 hours if device in Beijing
yyyy-MM-dd
// Safari family doesn't support, IE6-11 doesn't support
yyyy-MM-dd HH:mm:ss
No comments yet. Be the first to share your thoughts.