一.new Date()
据说有 4 種の方法があります:
new Date();
new Date(value);
new Date(dateString);
new Date(year, month[, day[, hour[, minutes[, seconds[, milliseconds]]]]]);
第 1 種はタイムスタンプの取得に使用:
// get ts
var now = Date.now || function() {
return new Date().getTime();
};
第 2 種はタイムスタンプを Date オブジェクトに変換:
// ts to Date
var ts2Date = function(ts) {
return new Date(ts);
};
第 3 種は日時文字列を Date オブジェクトに変換:
// string to Date
// eg. '2016/10/01 12:01:02'
// '2016/10/01'
var str2Date = function(str) {
return new Date(str);
};
第 4 種は一般的に使用しません。第 4 種には非常に厄介な問題があるためです(month は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);
};
// getter/setter 中、month は 0-11
var date = new Date(); // 今日は 2016-10-01
date.getMonth(); // 9
date.setMonth(10);
date.toString(); // Tue Nov 01 2016 11:46:58 GMT+0800 (China Standard Time)
第 4 種の方法内部ではおそらく setter を使用しているため、month は 0 から始まります
比較的に有用なのは第 3 種です。一般的に処理が必要な日時文字列は ISO 標準フォーマットであるためです。例えば 2016-10-01 12:01:02 ですが、これは JS では非標準的です
二.日時文字列フォーマット
非標準フォーマット
まずこれら 2 つを見てみましょう:
// new 一个 0 区时间
new Date('2016-10-01'); // Sat Oct 01 2016 08:00:00 GMT+0800 (China Standard Time)
// new 一个当前时区时间
new Date('2016/10/01'); // Sat Oct 01 2016 00:00:00 GMT+0800 (China Standard Time)
2 番目が正しく、1 番目は8 時間多いです。ブラウザは 1 番目传入的是 0 区時間と判断し、東八区ユーザーのために勝手に 8 時間を追加しました。それぞれ以下と等価です:
// 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');
したがって、絶対に使用してはいけませんyyyy-MM-dd。たとえ非常に確実に 0 区時間を new したい場合でも、このようにすべきではありません。他人が理解できない可能性があるためです。本当に 0 区時間を new したい場合、その等価フォーマット(GMT タイムゾーン識別子付きのもの)を使用すべきです
時間 'HH:mm:ss' を追加して再試行:
// new 一个 0 区时间
// Sat Oct 01 2016 12:01:02 GMT+0800 (China Standard Time)
new Date('2016-10-01 12:01:02');
// new 一个当前时区时间
// Sat Oct 01 2016 12:01:02 GMT+0800 (China Standard Time)
new Date('2016/10/01 12:01:02');
竟然一致しました。しかし、Safari(IOS Safari を含む)はyyyy-MM-dd HH:mm:ss フォーマットをサポートしていません。Safari は開始から現在(2016-10-01)までこのフォーマットをサポートしていません。非規範的であるため、サポートする予定がない可能性があります
yyyy/MM/dd HH:mm:ss も非規範的ですが、歴史が長いため、IE6 を含むすべてのブラウザがサポートしています
したがって、広くサポートされている非標準フォーマットは 2 つあります:
// 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
前者はデフォルトで現在のタイムゾーン時間、後者はタイムゾーンを設定できます
標準フォーマット
ES5.1 15.9.1.15 Date Time String Format まで日時文字列のフォーマット標準がありませんでした:
// 0 区時間
YYYY-MM-DDTHH:mm:ss.sssZ
// 東边時間
YYYY-MM-DDTHH:mm:ss.sss+HH:mm
// 西边時間
YYYY-MM-DDTHH:mm:ss.sss-HH:mm
この仕様は 2011 年 6 月のものです。したがって、互換性 は想像の通りです。見た目はかなり奇妙ですが、標準を遵守する Safari はサポートしています。例えば:
// 0 区時間
// Sat Oct 01 2016 20:01:02 GMT+0800 (CST)
new Date('2016-10-01T12:01:02Z')
// 東 8 区時間
// Sat Oct 01 2016 12:01:02 GMT+0800 (CST)
new Date('2016-10-01T12:01:02+08:00')
同様に、0 区時間には勝手にタイムゾーンオフセットが追加されます。したがって、これら 2 つが簡単に考えられます:
new Date('2016-10-01T12:01:02+00:00')
new Date('2016-10-01T12:01:02-00:00')
これらはすべて Z と等価で、同様にローカライズオフセットされます
三.GMT と UTC
一般的にこれら 2 つは同じものと見なせます。どちらも世界標準時間を表します。北京は東八区に位置するため:
// 一般的に考えられる
北京時間 === UTC+8 === GMT+8
UTC と GMT はタイムゾーンの概念上一致していますが、UTC は精度を強調し、誤差がより小さいです。この誤差は UT に対する相対的なものです
GMT
GMT(Greenwich Mean Time グリニッジ標準時)は最初に定義された世界時間です。1884 年、各国代表がワシントンに集まり会議を開き、タイムゾーンについて合意に達しました。本初子午線を中心とし(0 区に位置)、東に 1 から 11 区、西に 1 から 11 区、合わせて 12 区(「東西 12 区」と呼ぶ)、合計24 のタイムゾーン です
0 区から標準時間を発表し、他の区は対応するオフセット量を加えてローカル時間を取得します
UT
UT(Universal Time 世界時)は天体観測に基づいて計算された時間です。UT 自体は広い概念であり、その下に UT0、UT1、UT2 などが含まれます。その中で UT0 は完全に天体の運行に基づいて計算された時間であり、UT1 は UT0 の基础上でいくつかの調整を行い、UT2 は UT0 と UT1 の基础上でさらにいくつかの調整を行いました。天体の運行にはいくつかの不確実性があるため(例えば地球の自転は等速ではなく、複雑な方法で加速と減速を行っています)、UT 時間は均一に流れているわけではありません。
UT は理論上の「正しい」時間です
UTC
UTC(Universal Time Coordinate 協定世界時)は原子時計に基づく時間です。原子時計とは何か?個人的には非常に小さく、長さが固定されており、これ以上分割できない時間セグメントであると考えています。したがって UTC の時間は均一です。UT 時間との誤差をできるだけ小さくするために、UTC は閏秒を導入しました(ある年の最後の 1 分が 61 秒になる)、以确保 UTC と UT1 の間の誤差が 0.9 秒以内になるようにしています。
UTC は GMT のタイムゾーン概念を認めているため、UTC は GMT にさらに高級な時計を換えたようなもので、GMT がどのような時計を使用しているかは分かりません
四.潜在的な問題
北京時間と最も差があるのは西 12 区(いくつかの小さな島のみ)です:
deltaH = (+8) - (-12) = 20
ローカル時間判断を作成した場合、例えば:
if (new Date() > new Date('2016/10/02')) {
alert('a new day');
}
異なるタイムゾーンのユーザーはすべて、手元のデバイスで 2016 年 10 月 2 日 0 時 0 分 0 ミリ秒以外を表示した時に a new day を見ます。これは問題ありません。しかし、シナリオがこの場合:
if (new Date() > new Date('2016/10/02')) {
alert('考试时间到,3 秒后回到首页');
setTimeout(function() {
location.href = '/index.html';
}, 3000);
}
ここで問題が大きくなります。北京時間 2016 年 10 月 2 日 0 時 0 分 0 ミリ秒以外で、試験状態が CLOSED に変更され、提出を受け付けなくなります。すると、他のタイムゾーンに位置するユーザーは問題に気づきます:
-
西 12 区に住む友人はあと 20 時間ゆっくり回答でき、提出时发现人家不要
-
東 12 区に住む友人はさらに悲惨で、4 時間早く採点されました
もちろん、一般的にはページに入ってまずサーバーに状態を求め、サーバー時間を基準とします。ローカル時間は信頼できない ためです(ユーザーはデバイス時間を自由に変更できる)、もう 1 つの理由は上で言及した通り:タイムゾーンの差異により他のタイムゾーンに位置するユーザー が困惑するからです
したがって、たとえローカル時間判断を使用する場合でも、このようにすべきです:
if (new Date() > new Date('02 October, 2016 GMT+0800')) {
alert('考试时间到,3 秒后回到首页');
setTimeout(function() {
location.href = '/index.html';
}, 3000);
}
ユーザーのローカル時間と北京時間を比較します。少なくともユーザーデバイス時間の場合、状態の一貫性を保証できます。もちろん、手動で時間を変更する問題は回避できません(例えば以前のいくつかの農場ゲームはローカル時間を使用していました)。したがって、できるだけ ローカル時間を判断基準にしないでください
五.まとめ
ローカル時間とはデバイスが所在するタイムゾーンの時間 を指します
最も互換性の良い日時文字列フォーマット:
// タイムゾーンをサポートしない
2016/10/01 12:01:02
yyyy/MM/dd HH:mm:ss
// タイムゾーンをサポート
new Date('01 October, 2016 GMT+0800')
week, dd month yyyy HH:mm:ss GMT±HHmm
ES5.1 標準日時文字列フォーマット:
2016-10-01T12:01:02+08:00
YYYY-MM-DDTHH:mm:ss.sss±HH:mm
絶対に使用してはいけない 日時文字列フォーマット:
// 互換性は問題ないが、強制オフセットされる。例えばデバイスが北京なら +8 時間
yyyy-MM-dd
// Safari 全家都不サポート、IE6-11 都不サポート
yyyy-MM-dd HH:mm:ss
参考資料
-
前端工程研究:關於 JavaScript 中 Date 型別的常見地雷與建議作法:また 1 人の MVP 先輩を発見
コメントはまだありません