1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Dayjs で割と簡単に「たった今」「23秒前」のような相対表記を実現するワークアラウンド

Posted at

バージョン

dayjs@1.11.11 で動作確認しています。

相対表記の実装の基本

import dayjs from "dayjs";
import "dayjs/locale/ja";
import relativeTime from "dayjs/plugin/relativeTime";

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

まず標準の相対表記を実装するのはこれ↑だけです。

const now = new Date().getTime();
const secondsAgo = now - 1 * 1000;
const minutesAgo = now - 2 * 60 * 1000;
const hoursAgo = now - 2 * 60 * 60 * 1000;

console.log(dayjs(secondsAgo).fromNow());
console.log(dayjs(minutesAgo).fromNow());
console.log(dayjs(hoursAgo).fromNow());

// 数秒前
// 2分前
// 2時間前

「数秒前」じゃなくて、「たった今」とかにしたい

import dayjs from "dayjs";
import "dayjs/locale/ja";
import relativeTime from "dayjs/plugin/relativeTime";
import updateLocale from "dayjs/plugin/updateLocale";

dayjs.locale("ja");
dayjs.extend(relativeTime);
dayjs.extend(updateLocale);
dayjs.updateLocale("ja", {
  relativeTime: {
    future: "%s後",
    past: (value: string) => (value === "たった今" ? value : `${value}前`),
    s: "たった今",
    m: "1分",
    mm: "%d分",
    h: "1時間",
    hh: "%d時間",
    d: "1日",
    dd: "%d日",
    M: "1ヶ月",
    MM: "%dヶ月",
    y: "1年",
    yy: "%d年",
  },
});

Locale をこのように指定する必要がありますが、past の部分だけちょいと嫌な書き方になっています。
fromNow() で「〜〜前」をやろうとするとこの past のテンプレートを必ず通るわけですが、sに「たった今」が入っていると「たった今前」となってしまうんですね。
仕方ないので上のようにハードコーディングで判定する処理を入れます。

ちなみに relativeTime の変えたいところだけの指定はできず、全部指定しないとエラーになります。

「23秒前」のように1分未満もカウントしたい

リアルタイム性の高いアプリケーションではそうしたいこともあるでしょう。
しかし、relativeTime は ss をサポートしていないので、他と同じように ss: "%d秒" という指定ができません。

import dayjs from "dayjs";
import "dayjs/locale/ja";
import relativeTime from "dayjs/plugin/relativeTime";
import updateLocale from "dayjs/plugin/updateLocale";

dayjs.locale("ja");
dayjs.extend(relativeTime);
dayjs.extend(updateLocale);
dayjs.updateLocale("ja", {
  relativeTime: {
    future: "%s後",

    past: (value: string) => (value === "0秒" ? "たった今" : `${value}前`),
    // もしくはたった今の範囲を指定したい場合は
    past: (value: string) => {
      if (value.endsWith("")) {
        const seconds = Number(value.split("")[0]);
        // この場合、5秒未満なら「たった今」と表示され、5秒以上なら「23秒前」のように表示される
        return seconds < 5 ? "たった今" : `${seconds}秒前`;
      }
      return `${value}前`;
    },

    s: "%d秒",
    m: "1分",
    mm: "%d分",
    h: "1時間",
    hh: "%d時間",
    d: "1日",
    dd: "%d日",
    M: "1ヶ月",
    MM: "%dヶ月",
    y: "1年",
    yy: "%d年",
  },
});

ss はサポートされていないですが、s をテンプレートとした変数展開時には、他と同じようにその秒数が渡されているので、それを使います。

コード内 5 はもちろん自由に設定できます。

あまり嬉しいコードではないですが、とりあえずサクッと実現するならこれが一番簡単そう。

1
0
0

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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?