【JavaScript】Luxon で日付の操作・全実例38件!

こんにちは❗フリーランス・エンジニアの 九保すこひ です。

さてさて、この間Twitterをぼんやり眺めていると、どんぶラッコさんのツイートが目に入り、衝撃を受けることになりました。

それは・・・・・・

Moment.js はすでに非推奨です😭

という事実です。

実際 Moment.js 公式のアナウンス でもこのことが言及されていて、以下のように言っています。

(超要約)

Moment.js は古い時代の JavaScript だから、新プロジェクトからは代替パッケージを使ったほうがいいかもね。

そして、その「代替パッケージ」として一番最初に登場するのが正式な後継パッケージ Luxon(「らくそん」と読むようです) でした。(2021.04.29 現在)

そこで❗

今回はこのLuxonで日時を操作するため「実例記事」を書いてみることにします。

ぜひ皆さんのお役に立てましたら嬉しいです😊✨

「読み方が分からないパッケージは、
YouTubeでチェックしてます」

開発環境: Luxon 1.26.0

目次

日付オブジェクトを取得する

Luxonからオブジェクトを取得するにはいくつかの方法がありますが、使い勝手がよさそうな順でご紹介します。

現在の日付・時間で取得

一番シンプルな取得方法で、「たった今」の時刻を取得します。

const dt = luxon.DateTime.now();

DB形式から取得(例: 2021-01-02 03:04:05)

MySQLなどデータベースから取得した日付データを元にする場合です。

const dt = luxon.DateTime.fromSQL('2000-01-02 03:04:05');

なお、日付のみでもOKです。

const dt = luxon.DateTime.fromSQL('2021-01-02');

ちなみにLaravelとの連携は以下のようにするといいでしょう。

const dt = luxon.DateTime.fromSQL('{{ $item->created_at }}');

// もしくはヘルパー関数の場合

const dt = luxon.DateTime.fromSQL('{{ now() }}');

※ その他、ミリ秒付きでもOKなどいろいろなパターンがありますが、一番馴染みのあるフォーマットになっていますので、「迷ったら fromSQL() を使ってみる」という流れでもいいかもしれません。

オブジェクトから取得(例: { year: 2000 … })

年・月・日 などのデータをセットする方法です。

const dt = luxon.DateTime.fromObject({
    year: 2000,
    month: 1,
    day: 2
});

なお、年・月・日 が全て揃っている必要はなく、以下の場合は「2000/1/1 00:00:00」として取得できます。

const dt = luxon.DateTime.fromObject({ 
    year: 2000
});

また、以下は「今日の1時2分3秒」になります。

const dt = luxon.DateTime.fromObject({
    hour: 1,
    minute: 2,
    second: 3
});

指定フォーマットから取得

日付形式を指定する方法です。

例えば、「2000年、1月。日付は2日」という文字列からフォーマットを使って日付オブジェクトを取得してみましょう。

const text = '2000年、1月。日付は2日';
const dt = luxon.DateTime.fromFormat(text, 'yyyy年、M月。日付はd日');

JavaScript の日付オブジェクトから取得

JavaScriptで使えるノーマルな日付オブジェクトを使う方法です。

const dt = luxon.DateTime.fromJSDate(new Date());

なお、これは以下と同じになります。

const dt = luxon.DateTime.now();

言語設定をする

全体的に言語設定をする場合は、luxonを利用する前に以下のコードをセットしておく必要があります。

luxon.Settings.defaultLocale = 'ja';

また、個別にロケールを変更したい場合は以下のようにsetLocale()を使ってください。

dt.setLocale('ja').toFormat('EEE');

日付データを取得する

年を4桁で取得する(例: 2021)

const year = dt.year;

月を取得する(例: 4)

const month = dt.month;

日を取得する(例: 30)

const day = dt.day;

時間を取得する(例:15)

const hour = dt.hour;

もし、12時間単位で取得する場合はtoFormat()を使ってください。

const hour = dt.toFormat('h');

分を取得する(例: 51)

const minute = dt.minute;

秒を取得する(例: 38)

const second = dt.second;

ミリ秒を取得する(例: 345)

const millisecond = dt.millisecond

曜日を取得する(例: 水 or 水曜日)

luxon.Settings.defaultLocale = 'ja'; // 言語設定が必要です。

const dayOfWeek = dt.weekdayShort; // 水

もしくは曜日を省略しない場合です。

luxon.Settings.defaultLocale = 'ja'; // 言語設定が必要です。

const dayOfWeek = dt.weekdayLong; // 水曜日

Unixタイムスタンプを取得する(例: 946749845)

const timestamp = dt.toSeconds();

なお、ミリ秒の場合はこちら。

const timestamp = dt.toMillis();

日本向けの日付を取得する(例: 2021/1/2)

const date = dt.toLocaleString();

日本語表記の日付を取得する(例: 2021年1月2日)

const date = dt.toLocaleString(luxon.DateTime.DATE_FULL);

曜日つきの日付を取得する(例: 2000年1月2日(日))

const date = dt.toLocaleString(luxon.DateTime.DATE_MED_WITH_WEEKDAY);

曜日つきの日付を取得する(例: 2000年1月2日日曜日)

const date = dt.toLocaleString(luxon.DateTime.DATE_HUGE);

日本向けの時刻を取得する(例: 3:04)

const time = dt.toLocaleString(luxon.DateTime.TIME_SIMPLE);

日本向けの日時を取得する(例: 2000/1/2 3:04)

const time = dt.toLocaleString(luxon.DateTime.DATETIME_SHORT);

タイムゾーンを取得する(例: Asia/Tokyo)

const timezone = dt.zoneName;

指定したフォーマットで日時を取得(例: 2000.01.02)

const date = dt.toFormat('yyyy.MM.dd');

なお、フォーマットに使われるキーワードは以下を参考にしてください。

📝 参考URL: https://moment.github.io/luxon/docs/manual/formatting.html#table-of-tokens

日数を取得する

例えば、「今月は何日あるの?」が知りたい場合です。

const days = dt.daysInMonth;

また、年間の場合はこちら。

const days = dt.daysInYear;

※うるう年の場合は366日になります。

曜日を全て取得する

月〜日までのデータを全て取得する方法です。

const weekdays = luxon.Info.weekdays();

// 👉これは ["月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日", "日曜日"]

もし省略バージョンの曜日を取得する場合はshortをつけます。

const weekdays = luxon.Info.weekdays('short');

// 👉 これは、["月", "火", "水", "木", "金", "土", "日"]

日付を操作する

日時を進める(例: 2000/1/2 → 2000/1/5)

const newDt = dt.plus({ days: 3 }); // 3日進める

もちろん、daysだけでなくその他のパラメータも使えます。

const newDt = dt.plus({
    hours: 3,   // 3時間進める
    minutes: 4  // 4分進める
});

日時を戻す

こちらも「日時を進める」と同じくminus()を使うことで実装できます。

const newDt = dt.minus({
    days: 2,
    hours: 3,   // 3時間進める
    minutes: 4  // 4分進める
});

指定した日時へ移動する

例えば、「2000/1/2 03:04:05」から「2001/2/3 04:05:06」に移動する場合です。

const dt = luxon.DateTime.fromSQL('2000-01-02 03:04:05');
const newDt = dt.set({
    year: 2001,
    month: 2,
    day: 3,
    hour: 4,
    minute: 5,
    second: 6
});

もちろん、全ての項目をセットする必要はなく、「年だけ」とか「月と日だけ」を指定することもできます。

年・月・日などの開始位置へ移動

ある開始地点へ移動するにはstartOf()を使います。
例えば、現在が「2000/5/3 03:04:05」として、月の始めに移動してみましょう。

const newDt = dt.startOf('month'); // 2000-05-01 00:00:00

もちろん、month だけでなくyeardayhourなどでもつかえます。

年・月・日などの終了位置へ移動

ある終了地点へ移動するにはendOf()を使います。
例えば、現在が「2000/5/3 03:04:05」として、月の終わりに移動してみましょう。

const newDt = dt.endOf('month'); // 2000-05-31 23:59:59

もちろん、month だけでなくyeardayhourなどもつかえます。

日付をチェックする

日付として正しいかチェックする

例えば、「2000-02-31」はありえない日付ですが、こういったものをチェックする方法です。

const dt = luxon.DateTime.fromSQL('2000-02-31'); // 👈 ありえない日付

if(!dt.isValid) {

    console.log('日付が正しくありません!');

}

うるう年かどうかチェックする

例えば、2000年はうるう年のため366日ありますが、こういったものをチェックする方法です。

const dt = luxon.DateTime.fromSQL('2000-01-01'); // 👈 2000年は、うるう年です

if(dt.isInLeapYear) {

    console.log('うるう年です!');

}

同じ「年」や「月」かをチェックする

例えば、2つの日時が同じ年&月のものかどうかをチェックする方法です。

const dt1 = luxon.DateTime.fromSQL('2000-01-02');
const dt2 = luxon.DateTime.fromSQL('2000-01-03');

if(dt1.hasSame(dt2, 'month')) {

    console.log('同じ年・月です!');

}

ここで重要なのはmonthとした場合でも、単純に月だけを比較していないという部分です。つまり、上の例で言うとdt22001-01-03の場合、hasSame()falseとなります。

日付を比較する

2つの日付の差を取得する

例えば、以下2つの日付を比較して「どれだけ日数が違うか」を取得する場合です。

  • 2000-01-02
  • 2001-02-03
const dt1 = luxon.DateTime.fromSQL('2000-01-02');
const dt2 = luxon.DateTime.fromSQL('2001-02-03');

const diff = dt1.diff(dt2, 'days'); // 👈 months などもでもOKです
const diffDays = diff.days; // -398

現在時間との差を取得する

const dt1 = luxon.DateTime.fromSQL('2000-01-02');
const dt2 = luxon.DateTime.fromSQL('2001-02-03');

const diff = dt1.diffNow('days');
const diffDays = diff.days;
console.log(diffDays)

どちらが「先 or 後」の日時かを判別する

>>=などの比較演算子が使えます。

const dt1 = luxon.DateTime.fromSQL('2000-01-02');
const dt2 = luxon.DateTime.fromSQL('2001-02-03');

if(dt1 < dt2) {

    console.log('dt1 の方が古い日時です。');

}

開発者向け

中身を確認したい場合

開発者としてシンプルに日時の中身を取得したい場合はtoString()を使うといいでしょう。

console.log(dt.toString());

あたかも指定した日時を現在時刻とする

luxon.Settings.now = () => {

    return new Date('2000-01-01');

};
const currentDateTime = luxon.DateTime.now().toString();  // 👈 2000-01-01 になる

おまけ: Laravel(Webpack)で Luxon をインストール

このブログではLaravelの記事をよく公開していますので、おまけとしてLaravelLuxonをインストールする方法をご紹介します。

まず以下のコマンドでパッケージをインストールしてください。

npm install --save luxon

インストールが完了したら、ビルド用のコードを追加します。

resources/js/app.js

// 省略

window.luxon = require('luxon'); // 👈 ここを追加しました

これでビルドされたjsファイルを読み込めばCDNと同じように使うことができます。

<html>
<body>
    <script src="/js/app.js"></script>
    <script>

        const dt = luxon.DateTime.now();

    </script>
</body>
</html>

ちなみに:なぜ Day.js を選ばなかったか

完全に「これは個人の感想です」というやつなのですが、Day.jsがあまり私には合わなかったので、その理由も備忘録として書いておくことにしました。

理由としてはシンプルに、

うーん、JavaScript のそういうところが好きじゃないからパッケージを使いたいんだけど…

というものです。

例えば、「年」「月」「日」を取得するコードを見てみましょう。

const dt = dayjs('2000-01-01');

console.log(dt.year());

console.log(dt.month()); // これは 0 になる(0〜11)

console.log(dt.day()); // これは曜日になるので、date() が正解

このように、month()0〜11で返ってきますし、day()では「日」を取得することができません。

これって、以前公開した記事 JavaScriptのハマりどころ全11件! のように微妙にワナが用意されてるような状態で、あまり直感的ではないと感じました。(プログラム初学者にもやさしくないですよね…😫)

今回の記事を書き始めたときは、「軽量に動く」&「スターが一番多い」Day.jsを検討していましたが、こういう理由で結局Luxonを選ぶことになりました。

おわりに

ということで、今回はJavaScriptの日付パッケージLuxonの使い方をまとめてみました。

正直なところ、まだまだ他にも機能はたくさんあるのですが、さすがに多すぎるので、「開発するには最低限これだけあればいいだろう」と思うものをピックアップしてみました。

ちなみに、moment.jsと比べてみた感想ですが、moment.jsは以下のように短いコードでインスタンスを取得できるので、やはりこっちの方が好きかなというイメージでした。

const dt = moment('2000-01-01', 'YYYY-MM-DD');

これがLuxonの場合は、DateTimeをつけないといけません。

const dt = luxon.DateTime.fromSQL('2000-05-02');

なので個人的には、シンプルに以下のようにaxiosっぽい感じでいいのにな、と感じました。(Settingsなどと分けているので仕方ないといえば仕方ないですが・・・)

// ⚠これらは間違った書き方です!

const dt = luxon.fromSQL('2000-01-02');

// もしくは moment.js のように

const dt = luxon('2000-01-02');

・・・とは言え、この辺は実際の案件で使っていけばすぐ慣れる気もしています。ぜひ皆さんもチェックしてみてくださいね。

ではでは〜❗

「メガネの鼻の支えが
1本折れました・・・😫」

開発のご依頼お待ちしております 😊✨ お問い合わせ
また、こちらもお待ちしております。
  • 実案件の開発サポート: 詳細
  • ツイッターのフォロー: 詳細
  • 投げ銭のご支援: 詳細
どうぞよろしくお願いいたします!
このエントリーをはてなブックマークに追加       follow us in feedly