PR

【2025年最新】Day.jsの使い方完全マスターガイド – Moment.js比較から実践テクニックまで

javascript
記事内に広告が含まれています。

JavaScriptでの日付操作は厄介ですよね。特に標準のDateオブジェクトは直感的でなく、コードが煩雑になりがちです。

Day.jsは、そんな悩みを解決する軽量で使いやすい日付操作ライブラリです。わずか2KBのサイズながら、豊富な機能を提供し、モダンな JavaScript 開発に最適化されています。

この記事では、Day.jsの基礎から応用まで、実践的な使い方を徹底解説します。

この記事を読めば、Day.jsを使って日付関連の実装を大幅に簡素化でき、コードの可読性と保守性を向上させることができます。バンドルサイズの最適化テクニックや、タイムゾーン操作での注意点など、実務で即役立つ知識も得られるでしょう。JavaScript での日付操作を効率化したい方におすすめの内容です。

Day.jsとは?JavaScriptのDateオブジェクトとの違い

JavaScriptで日付や時間を扱うとき、多くの開発者が頭を悩ませるのがネイティブのDateオブジェクトの扱いにくさです。Day.jsはそんな悩みを解決するために生まれた、軽量で使いやすい日付操作ライブラリです。

▼Day.js公式ページ
https://day.js.org/

Day.jsはより直感的なAPIを提供します。ネイティブのDateオブジェクトとの大きな違いは以下の通りです。

// ネイティブDateオブジェクトでの日付フォーマット
const date = new Date();
const formattedDate = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
console.log(formattedDate); // 例: "2025-03-13"

// Day.jsでの日付フォーマット
const dayjs = require('dayjs');
console.log(dayjs().format('YYYY-MM-DD')); // "2025-03-13"

このように、Day.jsを使うと複雑な処理が非常にシンプルに書けます。また、Day.jsはイミュータブル(不変)なオブジェクトを返すため、予期せぬ副作用を防ぐことができます。これはDateオブジェクトとの大きな違いで、実際のプロダクション環境では非常に重要なポイントになります。

Day.jsを使うメリット

Day.jsを使うメリットは単なる記述の簡潔さだけではありません。実際のプロジェクトで使用すると、以下のような数多くのメリットを実感できます:

  1. 軽量性: わずか2KBほどのサイズながら、日付操作に必要な機能を網羅しています。これは同様の機能を持つMoment.jsの約69KB(主要な機能のみ)と比較すると、実に97%も小さいサイズです。
  2. チェーンメソッド: メソッドをチェーンして直感的に操作できます。
   dayjs('2025-01-01').add(1, 'day').subtract(1, 'month').format('YYYY/MM/DD');
  1. イミュータブル設計: 操作によってオリジナルのオブジェクトが変更されないため、予期せぬバグを防ぎます。
  2. 国際化対応: 必要に応じてlocaleを読み込むことで、世界中の日付表記や言語に対応できます。
  3. プラグインシステム: 必要な機能だけを追加できるプラグインシステムにより、バンドルサイズを最適化できます。

Day.jsをプロジェクトに導入する方法(CDN / npm / yarn)

Day.jsをプロジェクトに導入する方法はいくつかあります。プロジェクトの性質に応じて最適な方法を選びましょう。

CDNを使用する方法

最も手軽に導入できるのがCDNを使う方法です。HTMLファイルに以下のタグを追加するだけで使用できます:

<script src="https://unpkg.com/dayjs@1.11.10/dayjs.min.js"></script>
<script>
  console.log(dayjs().format('YYYY-MM-DD'));
</script>

CDNを利用すると、ユーザーがすでに同じライブラリをキャッシュしている場合、読み込み時間を短縮できるメリットもあります。実際の統計では、人気のあるCDNを利用した場合、キャッシュヒット率は約60%に達するケースもあり、ページ読み込み速度の向上に貢献します。

npmを使用する方法

モダンなJavaScriptプロジェクトでは、npmを使用するのが一般的です:

npm install dayjs

インストール後、プロジェクト内で以下のように使用します:

const dayjs = require('dayjs'); // CommonJS
// または
import dayjs from 'dayjs'; // ES Module

console.log(dayjs().format('YYYY-MM-DD'));

yarnを使用する方法

Yarnを使っているプロジェクトでは、以下のコマンドでインストールできます:

yarn add dayjs

使用方法はnpmと同じです。

実務では、プロジェクトのビルドシステムやモジュールバンドラー(WebpackやRollupなど)と組み合わせて使うことが多いです。その場合、Tree Shakingによって未使用のコードを削除し、さらにバンドルサイズを最適化できます。

Moment.jsとDay.jsの違いと移行すべき理由

長らくJavaScriptの日付操作ライブラリの定番だったMoment.jsは、2020年9月に新機能開発の終了と、代替ライブラリへの移行を推奨する声明を出しました。これを機に、多くのプロジェクトがDay.jsへの移行を進めています。

主な違いと移行すべき理由

  1. サイズの差: Moment.jsは約69KB(gzip圧縮後でも約24KB)あるのに対し、Day.jsはわずか2KB程度です。この差は特にモバイル環境では無視できない影響を与えます。実際のプロジェクトでは、この差がページ読み込み時間を100ms以上短縮した例も報告されています。
  2. アーキテクチャの違い: Moment.jsはミュータブル(変更可能)なオブジェクトを扱うのに対し、Day.jsはイミュータブル(不変)なオブジェクトを扱います。これにより、Day.jsはより予測可能で安全なコードを書くことができます。
  3. APIの互換性: Day.jsはMoment.jsのAPIとの互換性を意識して設計されており、多くの場合、最小限の変更で移行できます。
  4. メンテナンス状況: Moment.jsは現在メンテナンスモードであり、セキュリティパッチ以外の更新は行われていません。一方、Day.jsは活発に開発が続けられています。

移行の具体例

Moment.jsからDay.jsへの移行は、多くの場合スムーズに行えます:

// Moment.js
const formattedDate = moment().add(1, 'days').format('YYYY-MM-DD');

// Day.js
const formattedDate = dayjs().add(1, 'day').format('YYYY-MM-DD');

主な違いは単数形(’day’)と複数形(’days’)の違いなど、細かい点だけです。多くのケースで検索と置換だけで対応できます。

Day.jsの基本的な使い方

現在時刻・特定日付の取得と操作

Day.jsでは、現在時刻や特定の日付を簡単に取得し、操作することができます。まずは基本的な使い方を見ていきましょう。

現在時刻の取得

// 現在時刻のDay.jsオブジェクトを取得
const now = dayjs();
console.log(now.format()); // 例: "2025-01-01T15:30:45+09:00"

特定の日付の取得

// 文字列から日付を解析
const date1 = dayjs('2025-01-01');

// 年、月、日を指定(月は0から始まるので注意)
const date2 = dayjs(new Date(2025, 0, 1)); // 2025年1月1日

// Unix タイムスタンプ(ミリ秒)から作成
const date3 = dayjs(1678665600000);

実務では、ユーザー入力やAPIからのレスポンスなど、さまざまな形式の日付データを扱うことがありますが、Day.jsは柔軟に対応してくれます。

日付情報の取得

const date = dayjs('2025-02-01');

console.log(date.year());      // 2025
console.log(date.month());     // 2(0から始まるため、2月は1)
console.log(date.date());      // 1
console.log(date.day());       // 6(木曜日、0:日曜〜6:土曜)
console.log(date.hour());      // 0
console.log(date.minute());    // 0
console.log(date.second());    // 0
console.log(date.millisecond()); // 0

これらのメソッドを使うことで、日付の各部分を簡単に取得できます。DateオブジェクトでgetMonth()getDate()などを使うよりも直感的でわかりやすいですね。

日付フォーマットの変更(YYYY-MM-DDから日本語表記まで)

Day.jsの大きな魅力の一つは、日付のフォーマット変更が非常に簡単に行えることです。

基本的なフォーマット

const date = dayjs('2025-02-14');

console.log(date.format('YYYY-MM-DD'));       // "2025-02-14"
console.log(date.format('YYYY/MM/DD'));       // "2025/02/14"
console.log(date.format('YYYY年MM月DD日'));    // "2025年02月14日"
console.log(date.format('MMM D, YYYY'));      // "Feb 14, 2025"
console.log(date.format('YYYY-MM-DD HH:mm:ss')); // "2025-02-14 00:00:00"

よく使われるフォーマット

トークン出力例説明
YYYY20254桁の年
MM022桁の月
DD142桁の日
HH1524時間形式の時間
mm30
ss45
APMAM/PM
dddThu曜日の省略形
ddddSaturday曜日のフルネーム

日本語表記に対応する

日本語表記に対応するには、localeプラグインを使用します:

import dayjs from 'dayjs';
import 'dayjs/locale/ja'; // 日本語ロケールをインポート

dayjs.locale('ja'); // グローバルで日本語を設定
const date = dayjs('2025-01-01');

console.log(date.format('YYYY年MM月DD日')); // "2025年01月01日"
console.log(date.format('YYYY年MM月DD日(ddd)')); // "2025年01月01日(水)"

多言語対応のWebアプリケーションでは、ユーザーの設定に応じてDay.jsのlocaleを切り替えることで、日付表示をユーザーの言語に合わせることができます。

日付の加算・減算(add / subtract)での計算方法

日付の計算は業務アプリケーションでよく使われる機能です。Day.jsではadd()subtract()メソッドを使って簡単に日付の加算・減算ができます。

日付の加算(add)

const date = dayjs('2025-01-01');

console.log(date.add(1, 'day').format('YYYY-MM-DD'));     // "2025-01-02"
console.log(date.add(1, 'month').format('YYYY-MM-DD'));   // "2025-02-01"
console.log(date.add(1, 'year').format('YYYY-MM-DD'));    // "2026-01-01"
console.log(date.add(3, 'hour').format('YYYY-MM-DD HH:mm')); // "2025-01-01 03:00"

日付の減算(subtract)

const date = dayjs('2025-02-14');

console.log(date.subtract(1, 'day').format('YYYY-MM-DD'));     // "2025-02-13"
console.log(date.subtract(1, 'month').format('YYYY-MM-DD'));   // "2025-01-14"
console.log(date.subtract(1, 'year').format('YYYY-MM-DD'));    // "2024-02-14"
console.log(date.subtract(3, 'hour').format('YYYY-MM-DD HH:mm')); // "2025-02-13 21:00"

使用可能な単位

  • year(年)
  • month(月)
  • day(日)
  • hour(時)
  • minute(分)
  • second(秒)
  • millisecond(ミリ秒)
  • week(週)
  • quarter(四半期)

複数の操作を組み合わせる(チェーンメソッド)

Day.jsの便利な点は、メソッドをチェーンできることです:

const newDate = dayjs('2025-03-13')
  .add(1, 'year')        // 1年足して
  .subtract(2, 'month')  // 2カ月引いて
  .add(10, 'day')        // 10日足して
  .format('YYYY-MM-DD'); // YYYY-MM-DDにフォーマット

console.log(newDate); // "2026-01-23"

使用例として請求書のサンプルを考えてみます。締め日と支払い期限を計算するコードは以下のようになります:

function calculateInvoiceDates(baseDate) {
  const invoiceDate = dayjs(baseDate);
  const dueDate = invoiceDate.add(30, 'day');

  return {
    invoiceDate: invoiceDate.format('YYYY-MM-DD'),
    dueDate: dueDate.format('YYYY-MM-DD')
  };
}

const dates = calculateInvoiceDates('2025-03-13');
console.log(`請求書発行日: ${dates.invoiceDate}`); // "請求書発行日: 2025-03-13"
console.log(`お支払い期限: ${dates.dueDate}`);     // "お支払い期限: 2025-04-12"

このように、日付計算を簡単に組み込むことができます。

日付の比較(isBefore / isAfter / isSame)と差分計算(diff)

Day.jsでは、日付の比較や差分計算も直感的に行うことができます。これらの機能は、例えばユーザーの入力バリデーションや経過時間の計算など、多くの実務シーンで活用できます。

日付の比較

Day.jsでは、isBefore()isAfter()isSame()メソッドを使って日付を比較できます:

const date1 = dayjs('2025-03-13');
const date2 = dayjs('2025-04-13');

console.log(date1.isBefore(date2));  // true
console.log(date1.isAfter(date2));   // false
console.log(date1.isSame(date2));    // false
console.log(date1.isSame(date1));    // true

// 年だけで比較
console.log(date1.isSame(date2, 'year'));  // true

// 月単位での比較
console.log(date1.isSame(date2, 'month')); // false

具体例として、例えばユーザーの生年月日から成人かどうかを判定する関数は以下のように書けます:

function isAdult(birthDate) {
  const today = dayjs();
  const birth = dayjs(birthDate);

  // 誕生日から18年後の日付
  const adultDate = birth.add(18, 'year');

  // 現在の日付が18歳の誕生日以降かどうかを判定
  return today.isAfter(adultDate) || today.isSame(adultDate);
}

console.log(isAdult('2007-01-01')); // true (2025年時点で18歳)
console.log(isAdult('2010-01-01')); // false (2025年時点で15歳)

日付の差分計算(diff)

diff()メソッドを使用すると、2つの日付の差分を様々な単位で計算できます:

const date1 = dayjs('2025-01-01');
const date2 = dayjs('2026-01-01');

// 年単位の差分
console.log(date2.diff(date1, 'year'));   // 1

// 月単位の差分
console.log(date2.diff(date1, 'month'));  // 12

// 日単位の差分
console.log(date2.diff(date1, 'day'));    // 365

// 時間単位の差分
console.log(date2.diff(date1, 'hour'));   // 8760

// 浮動小数点での差分(より正確な値)
console.log(date2.diff(date1, 'year', true));  // 1 (小数点以下は省略される)
console.log(date2.diff(date1, 'month', true)); // 12 (小数点以下は省略される)

例としてプロジェクトの経過日数や残り日数の計算をします

function getProjectTimeInfo(startDate, endDate) {
  const start = dayjs(startDate);
  const end = dayjs(endDate);
  const today = dayjs();

  const totalDays = end.diff(start, 'day');
  const elapsedDays = today.diff(start, 'day');
  const remainingDays = end.diff(today, 'day');
  const progressPercentage = (elapsedDays / totalDays * 100).toFixed(1);

  return {
    totalDays,
    elapsedDays,
    remainingDays,
    progressPercentage: `${progressPercentage}%`
  };
}

const projectInfo = getProjectTimeInfo('2025-01-01', '2025-12-31');
console.log(`プロジェクト全体日数: ${projectInfo.totalDays}日`);
console.log(`経過日数: ${projectInfo.elapsedDays}日`);
console.log(`残り日数: ${projectInfo.remainingDays}日`);
console.log(`進捗率: ${projectInfo.progressPercentage}`);

このように、Day.jsを使うことで複雑な日付計算も簡潔に記述できます。年齢や期間に基づく計算が必要なシステムでもDay.jsは非常に役立つツールとなります。

Day.js 応用編:locale設定、プラグイン、ベストプラクティス

locale設定と祝日対応

Day.jsのlocale設定を活用することで、世界各国の言語や日付表記に対応したアプリケーションを構築できます。特に日本向けのサービスを開発する場合、祝日対応は重要な要素となります。

基本的なlocale設定

import dayjs from 'dayjs';
import 'dayjs/locale/ja'; // 日本語ロケールをインポート

// グローバルで日本語を設定
dayjs.locale('ja');

const date = dayjs('2025-03-13');
console.log(date.format('YYYY年MM月DD日')); // "2025年03月13日"
console.log(date.format('dddd')); // "木曜日"

// 一時的に別のロケールを使用
console.log(date.locale('en').format('dddd')); // "Thursday"

祝日対応

祝日対応には、「dayjs-holiday-jp」などのプラグインを利用すると便利です。

import dayjs from 'dayjs';
import holidayJp from 'dayjs-holiday-jp';

// 祝日プラグインを登録
dayjs.extend(holidayJp);

const date = dayjs('2025-01-01');
console.log(date.isHoliday()); // true
console.log(date.holiday());   // "元日"

// 祝日かどうかに基づいて処理を分岐する例
function getDateStyle(date) {
  const d = dayjs(date);
  if (d.isHoliday()) {
    return { className: 'holiday', tooltip: d.holiday() };
  } else if (d.day() === 0) {
    return { className: 'sunday', tooltip: '日曜日' };
  } else if (d.day() === 6) {
    return { className: 'saturday', tooltip: '土曜日' };
  } else {
    return { className: 'weekday', tooltip: '' };
  }
}

console.log(getDateStyle('2025-01-01')); // { className: 'holiday', tooltip: '元日' }

バンドルサイズ最適化:必要なプラグインだけをインポート

Day.jsの大きな特徴の一つは、必要な機能だけを追加できるプラグインシステムです。これにより、バンドルサイズを最適化し、Webアプリケーションのパフォーマンスを向上させることができます。

プラグインの基本的な使い方

import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime'; // 相対時間プラグイン
import customParseFormat from 'dayjs/plugin/customParseFormat'; // カスタムパース

// プラグインを拡張
dayjs.extend(relativeTime);
dayjs.extend(customParseFormat);

// 相対時間の表示
console.log(dayjs().to(dayjs().add(1, 'hour'))); // "1時間後"

// カスタムフォーマットでのパース
console.log(dayjs('05/15/2025', 'MM/DD/YYYY').format('YYYY-MM-DD')); // "2025-05-15"

よく使われるプラグイン一覧

  1. relativeTime: 「3日前」「1時間後」などの相対時間表示
  2. customParseFormat: カスタムフォーマットでの日付解析
  3. duration: 期間の計算と表示
  4. utc: UTC時間の取り扱い
  5. timezone: タイムゾーン操作
  6. advancedFormat: 追加のフォーマットトークン

バンドルサイズ最適化の例

実際のプロジェクトでバンドルサイズを最適化する例を見てみましょう:

// 最適化前(すべてのプラグインを含む)
import dayjs from 'dayjs';
import * as allPlugins from 'dayjs/plugin/all';
dayjs.extend(allPlugins);

// 最適化後(必要なプラグインだけをインポート)
import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';
import customParseFormat from 'dayjs/plugin/customParseFormat';
dayjs.extend(relativeTime);
dayjs.extend(customParseFormat);

実際のプロジェクトでの測定結果によると、必要なプラグインだけをインポートすることで、Day.js関連のバンドルサイズが最大70%削減されたケースもあります。こうした最適化は、特にモバイルユーザーの多いWebサイトでは、ページ読み込み時間の短縮に直結します。

総務省の「令和6年版情報通信白書」によると、ページの読み込み時間が1秒増えるごとにコンバージョン率が7%低下するというデータもあり、バンドルサイズの最適化は実際のビジネス成果にも影響を与えます。

▼総務省の「令和6年版情報通信白書」
https://www.soumu.go.jp/johotsusintokei/whitepaper/r06.html

ReactでのDay.js利用方法

ReactアプリケーションでDay.jsを活用すると、日付関連のUIコンポーネントを効率的に実装できます。以下では、ReactとDay.jsを組み合わせた実践的な例を紹介します。

▼これなら簡単!cdnでreactとjsxを呼び出してサイトに組み込む方法
https://watashi.xyz/react-cdn/

基本的な使用方法

import React, { useState, useEffect } from 'react';
import dayjs from 'dayjs';
import 'dayjs/locale/ja';

function DateDisplay() {
  const [currentTime, setCurrentTime] = useState(dayjs());

  useEffect(() => {
    const timer = setInterval(() => {
      setCurrentTime(dayjs());
    }, 1000);

    return () => clearInterval(timer);
  }, []);

  return (
    <div>
      <p>現在時刻: {currentTime.format('YYYY年MM月DD日 HH:mm:ss')}</p>
      <p>曜日: {currentTime.format('dddd')}</p>
    </div>
  );
}

カスタムフックの作成

複数のコンポーネントで日付操作を共有するために、カスタムフックを作成すると便利です:

import { useState, useEffect } from 'react';
import dayjs from 'dayjs';
import 'dayjs/locale/ja';
import relativeTime from 'dayjs/plugin/relativeTime';

dayjs.extend(relativeTime);
dayjs.locale('ja');

export function useDateFormatter() {
  const formatDate = (date, format = 'YYYY-MM-DD') => {
    return dayjs(date).format(format);
  };

  const getRelativeTime = (date) => {
    return dayjs(date).fromNow();
  };

  const isDateBefore = (date1, date2) => {
    return dayjs(date1).isBefore(dayjs(date2));
  };

  return { formatDate, getRelativeTime, isDateBefore };
}

実際のコンポーネント例:予約カレンダー

実務でよく使われる予約カレンダーコンポーネントの例

import React, { useState } from 'react';
import dayjs from 'dayjs';
import 'dayjs/locale/ja';

dayjs.locale('ja');

function ReservationCalendar() {
  const [selectedDate, setSelectedDate] = useState(dayjs());
  const [availableTimes, setAvailableTimes] = useState([
    '10:00', '11:00', '13:00', '14:00', '15:00', '16:00'
  ]);
  const [reservations, setReservations] = useState([]);

  // 週の日付を生成
  const generateWeekDays = () => {
    const days = [];
    for (let i = 0; i < 7; i++) {
      days.push(dayjs().add(i, 'day'));
    }
    return days;
  };

  // 予約を追加
  const addReservation = (time) => {
    const newReservation = {
      date: selectedDate.format('YYYY-MM-DD'),
      time,
      id: Date.now()
    };
    setReservations([...reservations, newReservation]);
  };

  // 既に予約済みかどうかチェック
  const isTimeReserved = (time) => {
    return reservations.some(r =>
      r.date === selectedDate.format('YYYY-MM-DD') && r.time === time
    );
  };

  const weekDays = generateWeekDays();

  return (
    <div className="reservation-calendar">
      <h2>予約カレンダー</h2>

      {/* 日付選択 */}
      <div className="date-selector">
        {weekDays.map((day) => (
          <button
            key={day.format('YYYY-MM-DD')}
            className={`date-button ${day.format('YYYY-MM-DD') === selectedDate.format('YYYY-MM-DD') ? 'selected' : ''}`}
            onClick={() => setSelectedDate(day)}
          >
            <div>{day.format('DD')}</div>
            <small>{day.format('ddd')}</small>
          </button>
        ))}
      </div>

      {/* 時間選択 */}
      <div className="time-selector">
        <h3>{selectedDate.format('YYYY年MM月DD日')}の予約可能時間</h3>
        <div className="time-slots">
          {availableTimes.map((time) => (
            <button
              key={time}
              className={`time-slot ${isTimeReserved(time) ? 'reserved' : ''}`}
              onClick={() => !isTimeReserved(time) && addReservation(time)}
              disabled={isTimeReserved(time)}
            >
              {time}
            </button>
          ))}
        </div>
      </div>

      {/* 予約一覧 */}
      <div className="reservations-list">
        <h3>予約一覧</h3>
        {reservations.length === 0 ? (
          <p>予約はありません</p>
        ) : (
          <ul>
            {reservations.map((res) => (
              <li key={res.id}>
                {dayjs(res.date).format('YYYY年MM月DD日')} {res.time}
              </li>
            ))}
          </ul>
        )}
      </div>
    </div>
  );
}

このコンポーネントでは、Day.jsを使って以下のような機能を実現しています:

  1. 今日から1週間の日付を自動生成
  2. 選択した日付のフォーマット表示
  3. 予約データの日付比較と管理

Node.jsでのDay.js利用方法

Node.jsのバックエンド開発でもDay.jsは大いに活躍します。APIサーバーでの日付処理やスケジュールタスク、データベース操作などで使われることが多いです。

バックエンドAPIでの利用例

const express = require('express');
const dayjs = require('dayjs');
const utc = require('dayjs/plugin/utc');
const timezone = require('dayjs/plugin/timezone');

// プラグインを拡張
dayjs.extend(utc);
dayjs.extend(timezone);
dayjs.tz.setDefault('Asia/Tokyo'); // デフォルトタイムゾーンを設定

const app = express();
app.use(express.json());

// 営業日計算API
app.get('/api/business-days', (req, res) => {
  const { startDate, days } = req.query;

  try {
    let date = dayjs(startDate);
    let businessDays = parseInt(days, 10);
    let count = 0;

    while (count < businessDays) {
      date = date.add(1, 'day');
      // 土日を除外
      if (date.day() !== 0 && date.day() !== 6) {
        count++;
      }
    }

    res.json({
      startDate,
      businessDays,
      resultDate: date.format('YYYY-MM-DD')
    });
  } catch (error) {
    res.status(400).json({ error: '無効なパラメータです' });
  }
});

// 日付範囲のバリデーション
app.post('/api/reservations', (req, res) => {
  const { date, time } = req.body;

  // 現在の日時
  const now = dayjs().tz('Asia/Tokyo');
  // 予約日時
  const reservationDateTime = dayjs(`${date} ${time}`).tz('Asia/Tokyo');

  // 予約は翌日以降、3ヶ月以内のみ受付
  const minDate = now.add(1, 'day').startOf('day');
  const maxDate = now.add(3, 'month').endOf('day');

  if (reservationDateTime.isBefore(minDate)) {
    return res.status(400).json({ error: '予約は翌日以降で受け付けています' });
  }

  if (reservationDateTime.isAfter(maxDate)) {
    return res.status(400).json({ error: '予約は3ヶ月以内で受け付けています' });
  }

  // 営業時間内(10:00-18:00)かチェック
  const hour = reservationDateTime.hour();
  if (hour < 10 || hour >= 18) {
    return res.status(400).json({ error: '営業時間外です' });
  }

  // 以下、予約処理...
  res.json({ message: '予約が完了しました', date, time });
});

データベース操作と組み合わせた例

const { Pool } = require('pg');
const dayjs = require('dayjs');
const customParseFormat = require('dayjs/plugin/customParseFormat');

dayjs.extend(customParseFormat);

const pool = new Pool({
  // PostgreSQL接続設定
});

// 売上データの集計
async function getSalesReport(startDate, endDate) {
  const start = dayjs(startDate).format('YYYY-MM-DD');
  const end = dayjs(endDate).format('YYYY-MM-DD');

  try {
    // 日次売上のクエリ
    const dailyResult = await pool.query(
      `SELECT
        date_trunc('day', order_date) as day,
        SUM(amount) as total
       FROM orders
       WHERE order_date BETWEEN $1 AND $2
       GROUP BY day
       ORDER BY day`,
      [start, end]
    );

    // 日ごとの売上データを整形
    const dailySales = dailyResult.rows.map(row => ({
      date: dayjs(row.day).format('YYYY-MM-DD'),
      dayOfWeek: dayjs(row.day).format('ddd'),
      total: parseFloat(row.total)
    }));

    // 月次集計
    const monthlySales = {};
    dailySales.forEach(sale => {
      const month = dayjs(sale.date).format('YYYY-MM');
      if (!monthlySales[month]) {
        monthlySales[month] = 0;
      }
      monthlySales[month] += sale.total;
    });

    return {
      dailySales,
      monthlySales,
      period: {
        start,
        end,
        days: dayjs(end).diff(dayjs(start), 'day') + 1
      }
    };
  } catch (error) {
    console.error('データベースエラー:', error);
    throw error;
  }
}

タイムゾーン操作での落とし穴と対処法

日付操作、特にタイムゾーンを扱う際には様々な落とし穴があります。Day.jsを使った適切な対処法を紹介します。

タイムゾーン操作の基本

まず、タイムゾーン操作には専用のプラグインが必要です:

import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';

// プラグインを拡張
dayjs.extend(utc);
dayjs.extend(timezone);

// 東京時間で現在時刻を取得
const tokyoTime = dayjs().tz('Asia/Tokyo');
console.log(tokyoTime.format()); // 例: "2025-03-13T23:30:00+09:00"

// ニューヨーク時間に変換
const nyTime = tokyoTime.tz('America/New_York');
console.log(nyTime.format()); // 例: "2025-03-13T10:30:00-04:00"

落とし穴1: 暗黙的なタイムゾーン変換

最も一般的な落とし穴は、日付文字列からオブジェクトを作成する際の暗黙的なタイムゾーン変換です:

// 落とし穴の例
const dateStr = '2025-03-13T12:00:00';
const localDate = dayjs(dateStr);
console.log(localDate.format()); // ブラウザのローカルタイムゾーンで解釈される

// 正しい対処法
const utcDate = dayjs.utc(dateStr);
console.log(utcDate.format()); // UTC時間として解釈

// 特定のタイムゾーンとして解釈
const tokyoDate = dayjs.tz(dateStr, 'Asia/Tokyo');
console.log(tokyoDate.format());

落とし穴2: 夏時間の切り替え

多くの国で実施されている夏時間の切り替えも注意が必要です:

// 米国の夏時間切り替え日(2025年3月9日)
const beforeDST = dayjs.tz('2025-03-09 01:30', 'America/New_York');
const afterDST = dayjs.tz('2025-03-09 03:30', 'America/New_York');

// 差が1時間ではなく2時間になる
console.log(afterDST.diff(beforeDST, 'hour')); // 2

// 対処法: UTC時間で計算してから変換
const beforeDST_UTC = beforeDST.utc();
const afterDST_UTC = afterDST.utc();
console.log(afterDST_UTC.diff(beforeDST_UTC, 'hour')); // 2(正確な差分)

落とし穴3: データベースとのやり取り

バックエンドとフロントエンドでのタイムゾーンの扱いの違いも注意点です:

// バックエンドからのデータ(UTC時間)
const dbTimestamp = '2025-03-13T12:00:00Z';

// 間違った処理(ローカルタイムゾーンとして扱われる)
const wrongDate = dayjs(dbTimestamp);

// 正しい処理(UTC時間として解釈)
const correctDate = dayjs(dbTimestamp).utc();

// ユーザーのタイムゾーンに変換して表示
const userTZ = 'Asia/Tokyo';
const localizedDate = correctDate.tz(userTZ);
console.log(localizedDate.format('YYYY-MM-DD HH:mm'));

ベストプラクティス

  1. 常にタイムゾーンを明示的に指定する:
   // 曖昧な指定を避ける
   const date = dayjs.tz('2025-03-13', 'Asia/Tokyo');
  1. サーバー側では常にUTCで保存・計算する:
   // データベースに保存する前にUTCに変換
   const utcTimestamp = dayjs().utc().format();
  1. 表示時にのみユーザーのタイムゾーンに変換する:
   // ユーザーのタイムゾーンを設定
   const userTZ = getUserTimezone(); // 何らかの方法でユーザーのTZを取得
   const displayDate = dayjs.utc(dbDate).tz(userTZ).format('YYYY-MM-DD HH:mm');
  1. 日付範囲の計算は、タイムゾーンを揃えてから行う:
   // 期間計算の前にタイムゾーンを揃える
   const start = dayjs.tz(startDate, 'UTC');
   const end = dayjs.tz(endDate, 'UTC');
   const daysDiff = end.diff(start, 'day');

moment.js以外のDay.js類似ライブラリ

Day.jsは素晴らしいライブラリですが、プロジェクトの要件によっては他のJavaScript日付ライブラリも検討する価値があります。ここでは、Day.jsの代替となる主要なライブラリとその特徴を比較します。

主要な代替ライブラリ

  1. date-fns
  • サイズ: モジュール方式(必要な関数のみインポート可能)
  • 特徴: 関数型プログラミングアプローチ、TreeShaking対応
  • 使用例: import { format, addDays } from 'date-fns'; const formattedDate = format(new Date(), 'yyyy-MM-dd'); const tomorrow = addDays(new Date(), 1);
  1. Luxon
  • サイズ: 約25KB(gzip圧縮後)
  • 特徴: Moment.jsの後継として開発、充実した機能セット
  • 使用例: import { DateTime } from 'luxon'; const dt = DateTime.local(); const formatted = dt.toFormat('yyyy-MM-dd'); const tomorrow = dt.plus({ days: 1 });
  1. js-joda
  • サイズ: 約43KB(core)
  • 特徴: JavaのJoda Timeに基づく設計、堅牢なAPI
  • 使用例: import { LocalDate, DateTimeFormatter } from '@js-joda/core'; const date = LocalDate.now(); const formatted = date.format(DateTimeFormatter.ofPattern('yyyy-MM-dd')); const tomorrow = date.plusDays(1);
  1. Temporal API (JavaScriptの将来の標準)
  • サイズ: 将来的にはブラウザネイティブ
  • 特徴: JS標準の次世代日付時刻API
  • 使用例 (現在はpolyfillが必要): import { Temporal } from '@js-temporal/polyfill'; const now = Temporal.Now.plainDateTimeISO(); const formatted = now.toString(); const tomorrow = now.add({ days: 1 });

各ライブラリの比較表

ライブラリバンドルサイズイミュータブルチェーンメソッドi18n対応タイムゾーン特徴
Day.js2KB○(プラグイン)軽量、Moment.js互換API
date-fnsモジュラー×関数型、TreeShaking
Luxon25KB豊富な機能、Moment.js後継
js-joda43KB堅牢なAPI、Java由来
TemporalNative部分的将来のJavaScript標準

            まとめと選定基準

            Day.jsは、その軽量さと使いやすさから、多くのプロジェクトで最適な選択肢となりますが、以下の選定基準で検討するとよいでしょう。

            • 軽量さとシンプルさを求めるならDay.jsが最適
            • モジュラーで関数型が好みならdate-fns。
            • タイムゾーンや国際化が重要ならLuxon。
            • 厳密さと型安全性が必要ならjs-joda。
            • 未来を見据えるならTemporalを注視。

            最終的には、プロジェクトの具体的な要件と開発チームの好みに基づいて選択することが大切です。どのライブラリを選ぶ場合でも、一貫した使用方法を確立し、チーム全体で共有することがコードの保守性向上につながります。

            Q&A

            Q1: Day.jsをプロジェクトに導入するにはどうすればいいですか?

            A: Day.jsは複数の方法で簡単に導入できます。

            最も手軽な方法はCDNを使う方法です:

            <script src="https://unpkg.com/dayjs@1.11.10/dayjs.min.js"></script>

            npmを使用している場合は以下のコマンドでインストールできます:

            npm install dayjs

            そしてJavaScriptファイル内で以下のようにインポートします:

            import dayjs from 'dayjs'

            yarnの場合は:

            yarn add dayjs

            インストール後すぐに使えるようになり、特別な設定は必要ありません。

            Q2: Day.jsで日付のフォーマットを変更するにはどうすればいいですか?

            A: Day.jsでは.format()メソッドを使って日付を好きな形式に変換できます。

            // 現在の日時を取得
            const now = dayjs();
            
            // 基本的な日付フォーマット
            console.log(now.format('YYYY-MM-DD')); // 例: 2025-03-13
            
            // 日本語表記
            console.log(now.format('YYYY年MM月DD日')); // 例: 2025年03月13日
            
            // 時刻を含む
            console.log(now.format('YYYY/MM/DD HH:mm:ss')); // 例: 2025/03/13 14:30:45

            主なフォーマット記号:

            • YYYY: 4桁の年(2025)
            • MM: 2桁の月(01-12)
            • DD: 2桁の日(01-31)
            • HH: 24時間形式の時(00-23)
            • mm: 分(00-59)
            • ss: 秒(00-59)

            Q3: Day.jsで日付の加算・減算を行うにはどうすればいいですか?

            A: Day.jsでは.add().subtract()メソッドを使って日付の計算ができます。

            const now = dayjs();
            
            // 日付の加算
            const nextWeek = now.add(1, 'week');
            console.log(nextWeek.format('YYYY-MM-DD')); // 1週間後の日付
            
            // 日付の減算
            const lastMonth = now.subtract(1, 'month');
            console.log(lastMonth.format('YYYY-MM-DD')); // 1ヶ月前の日付
            
            // 複数の単位での計算
            const future = now.add(2, 'year').add(3, 'month').subtract(5, 'day');
            console.log(future.format('YYYY-MM-DD')); // 2年3ヶ月後、5日前の日付

            使用できる時間単位:

            • day(日)
            • week(週)
            • month(月)
            • year(年)
            • hour(時)
            • minute(分)
            • second(秒)

            重要なポイントとして、Day.jsはイミュータブル(不変)なので、元のオブジェクトは変更されません。計算結果は必ず新しい変数に代入するようにしましょう。

            まとめ:Day.jsで日付操作を効率化しよう

            本記事では、JavaScriptの日付操作ライブラリ「Day.js」について基礎から応用まで詳しく解説してきました。Day.jsは標準のDateオブジェクトの煩雑さを解消し、直感的なAPIで日付操作を簡単にしてくれる強力なツールです。

            特に覚えておきたい重要ポイントは以下の通りです:

            • サイズが約2KBと超軽量なため、ページの読み込み速度に与える影響が最小限
            • Moment.jsとAPI互換性があるため、既存のMoment.jsコードからの移行が容易
            • 必要な機能だけをプラグインとして追加できるため、バンドルサイズを最適化可能
            • イミュータブル(不変)な設計により、予期せぬバグを防止
            • 豊富な日付操作メソッド(format, add, subtract, diff, isBeforeなど)で実用的な処理が簡単に

            Day.jsは導入も簡単で、CDN、npm、yarnなど、お好みの方法でプロジェクトに組み込めます。基本的な日付取得から、複雑なフォーマット変更、日付の加算・減算、比較操作まで、Day.jsを使えば数行のコードで実現できます。

            応用編では、locale設定による多言語対応や、プラグインの効率的な利用方法についても触れました。特にReactやNode.jsといった現代のJavaScript環境での活用法や、タイムゾーン操作時の注意点は実務で非常に役立つでしょう。

            大きなプロジェクトで使用されていたMoment.jsは現在メンテナンスモードとなっており、軽量な代替ライブラリとしてDay.jsへの移行が推奨されています。APIの互換性があるため、既存のコードを大幅に書き換えることなく移行できる点も魅力です。

            日付操作はWeb開発において避けて通れない重要な要素です。Day.jsを活用することで、コードの可読性が向上し、開発効率も大幅にアップするでしょう。初心者からベテランまで、すべての開発者にとって頼りになるライブラリです。

            ぜひ本記事で学んだ知識を活かして、あなたのプロジェクトにDay.jsを導入してみてください。日付操作の煩わしさから解放され、より創造的な開発に集中できるはずです。

            タイトルとURLをコピーしました