LoginSignup
0
0

More than 1 year has passed since last update.

【Javascript】日時を常にJST日本時間で表示したい【IE11対応】

Last updated at Posted at 2021-09-27

はじめに

Javascriptのnew Date関数で生成した日付はタイムゾーンの影響を受けてしまいます。
タイトルの通り「日時を常にJST日本時間で表示したい」場合は、タイムゾーンを考慮したコードを書く必要があります。

具体的にどういうこと?

下記のようなコードを書いてみるとわかりやすいです。

.js
const timestamp = 1632322799;
const date = new Date(timestamp * 1000).toLocaleString();
const formattedDate = //【省略】dateをyyyy/mm/dd hh:mm:ssに整形

console.log(formattedDate);

console.log 結果の日時に注目してください。

タイムゾーン名称 タイムゾーンID 略称 UTCからのオフセット console.log 結果
ハワイ・アリューシャン標準時 Pacific/Honolulu HAST -10:00 2021/09/22 4:59:59
ニューファンドランド標準時 America/St_Johns NST -03:30 2021/09/22 12:29:59
グリニッジ標準時 Europe/London GMT +00:00 2021/09/22 14:59:59
日本標準時 Asia/Tokyo JST +09:00 2021/09/22 23:59:59
ロードハウ標準時 Australia/Lord_Howe LHST +10:30 2021/09/23 1:29:59

上記のようにPCのタイムゾーン設定により出力される日時が変化してしまっています。

ちなみにPCのタイムゾーン設定はWindows/Mac共に簡単に変更できるので
誰でもブラウザで表示確認できることです:ok_hand:

今回やりたいことまとめ

  • Unixタイムスタンプを日時に変換して出力
  • 日時は常にJST日本時間で表示
  • モダンブラウザ+IE11にも対応
  • できればIE11対応のためにポリフィルは入れたくない

今回はタイムスタンプを日時に変換したいのでnew Date(timestamp * 1000)としています。
もちろんnew Date()new Date('2021-09-25')といった形でも同じ対応が可能です。

【結論】date-fns + date-fns-tzで対応

.js
import { format } from 'date-fns';
import { utcToZonedTime } from 'date-fns-tz';

const timestamp = 1632322799;
const formattedDate = format(utcToZonedTime(timestamp * 1000, '+09:00'), 'yyyy/MM/dd HH:mm:ss');

console.log(formattedDate);

ポイントは'+09:00'の部分。この書き方のおかげでIE11ポリフィルなしで実行できています。
'Asia/Tokyo'とも書けますが、IE11で動かすには'+09:00'のように、UTCからのオフセットを記述する必要があります。

参考

If you do not wish to use a polyfill the time zone option can still be used, but only with time zone offsets such as '-0200' or '+04:00' and not IANA time zone names.

Google翻訳した日本語はこちら。

ポリフィルを使用したくない場合でも、タイムゾーンオプションを使用できますが、IANAタイムゾーン名ではなく、「-0200」や「+04:00」などのタイムゾーンオフセットでのみ使用できます。

結論に至るまでに失敗した方法を紹介

JavaScript(timeZone)

ユーザー環境のlocaleを指定+タイムゾーンをAsia/Tokyoと指定するパターンです。

ダメだった理由

  • timeZoneプロパティがIE11未対応のためエラーが発生
.js
const timestamp = 1632322799;
const userLocale = (window.navigator.languages && window.navigator.languages[0]) || window.navigator.language || window.navigator.userLanguage || window.navigator.browserLanguage;
const date = new Date(timestamp * 1000).toLocaleString(userLocale, { timeZone: "Asia/Tokyo" });
const formattedDate = //【省略】dateをyyyy/mm/dd hh:mm:ssに整形

console.log(formattedDate);

JavaScript(getTimezoneOffset)

getTimezoneOffsetを使って固定する日時を計算するパターンです。
日本標準時(JST)に固定したいため、UTCからのオフセットを分単位で表すために(9 * 60)をしています。

ダメだった理由

  • サマータイム導入地域の場合、一部の日時がズレて表示される
.js
const timestamp = 1641308399;
const date = new Date(timestamp * 1000 + ((new Date().getTimezoneOffset() + (9 * 60)) * 60 * 1000));
const formattedDate = //【省略】dateをyyyy/mm/dd hh:mm:ssに整形

console.log(formattedDate);

サマータイム導入地域の場合、一部の日時がズレて表示される

Unixタイムスタンプが1632322799(2021/09/22 23:59:59)では問題ありませんが
サマータイム(夏時間・DST)が導入されている「ニューファンドランド」「ロードハウ」では、例えばタイムスタンプが1641308399(2022/01/04 23:59:59)だと時間がズレてしまいます。

タイムゾーン名称 タイムゾーンID 略称 UTCからのオフセット console.log 結果
ハワイ・アリューシャン標準時 Pacific/Honolulu HAST -10:00 2022/01/04 23:59:59
ニューファンドランド標準時 America/St_Johns NST -03:30 2022/01/04 22:59:59
グリニッジ標準時 Europe/London GMT +00:00 2022/01/04 23:59:59
日本標準時 Asia/Tokyo JST +09:00 2022/01/04 23:59:59
ロードハウ標準時 Australia/Lord_Howe LHST +10:30 2022/01/05 00:29:59

Day.js

ダメだった理由

  • IE11でエラーが発生
  • 一部Safariでエラーが発生
.js
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';

// タイムゾーンを扱うために必要なプラグインを使用
dayjs.extend(utc);
dayjs.extend(timezone);

// タイムゾーンを日本に設定
dayjs.tz.setDefault('Asia/Tokyo');

const timestamp = 1632322799;
const formattedDate = dayjs.tz(timestamp * 1000).format('YYYY/MM/DD HH:mm:ss');

console.log(formattedDate);

date-fnsよりも軽量かつMoment.jsに近い記述ができるDay.js
日時の処理が多いサイトかつ、サポートすべきブラウザで動くのであればこちらが最適解かと思います:muscle:

ひとこと

IE11対応は大変だなあ:frowning2:(132937289328回目)

0
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0