やりたいこと
Twitterのように、投稿日付を表示したい。「○分前」「○時間前」「○日前」など、現在時刻からの経過時間をざっくり表示したい。
moment.jsのfromNowでできる
moment.jsのfromNowを使えば実現できます。
デフォルトの設定では以下のように表示されます。未来の日時の場合は、(“前”の部分が”後”になります)
範囲 | Key(*1) | 表示例 |
---|---|---|
0 から 44 秒 | s | 数秒前 |
(ss から 44 秒(*2)) | ss | 44秒前 |
45 から 89 秒 | m | 1分前 |
90 秒 から 44 分 | mm | 2分前 ... 44分前 |
45 から 89 分 | h | 1時間前 |
90 分 から 21 時間 | hh | 2時間前 ... 21時間前 |
22 から 35 時間 | d | 1日前 |
36 時間 から 25 日 | dd | 2日前 ... 25日前 |
26 から 45 日 | M | 1ヶ月前 |
45 から 319 日 | MM | 2ヶ月前 ... 10ヶ月前 |
320 から 547 日 (1年半) | y | 1年前 |
548 日以上 | yy | 2年前 ... 20年前 |
(*1) Keyは、時間の丸めとなる閾値。例えば、Keyのm
は45なので、45分以上は1時間と見なされます。
(*2) ss
キーは、デフォルトでは44に設定されているため、”44秒前”のような表示はされません。ss
の値を10にしたきには、1から10秒は”数秒前”、11から44秒は”○秒前”と表示されます。
momentjs.com/13-relative-time-threshold.md at master · moment/momentjs.com · GitHub
moment#fromNowを動かしてみる
環境の準備とmomentパッケージのインストール
yarn + ES 6 + React(create-react-app使用)を利用するので、それ以外の環境の場合は適宜読み替えてください。
# 新規プロジェクトの作成 $ yarn create react-app moment-fromnow yarn create v1.9.4 # 中略 success Saved 10 new dependencies. info Direct dependencies ├─ react-dom@16.5.2 ├─ react-scripts@2.0.5 └─ react@16.5.2 # 中略 Success! Created moment-fromnow at /Users/yuka/react/moment-fromnow # 後略 $ cd moment-fromnow # momentパッケージの追加 $ yarn add moment # 中略 info All dependencies ├─ moment@2.22.2 ├─ react-dom@16.5.2 └─ react@16.5.2
シンプルなコード
簡単なコードを動かしてみます。
src/App.js
import React from 'react'; import moment from 'moment' // #1 import 'moment/locale/ja' // #2 const App = () => ( <div> {moment('2018-10-19 13:13:13').fromNow()} // #3 </div> ); export default App;
- momentをimportします(#1)。
moment/locale/ja
をimportし、日本語化します(#2)。- moment('2018-10-19 13:13:13’)で、201年10月19日13時13分13秒を表すmomentオブジェクトを作成し、
fromNow()
を呼び出します(#3)。
実行結果
サーバを起動して確認します。
$ yarn start
http://localhost:3000 を開きます。
無事表示されました。
様々な時刻でfromNow
の実行結果を確認する
簡単な動作確認はできたので、一通り全ての範囲の表示を確認します。
src/App.js
import React from 'react'; import moment from 'moment' import 'moment/locale/ja' import './App.css'; const DATE_FORMAT = 'YYYY-MM-DD HH:mm:ss' const App = () => { let now = moment(); const timeAgoArr = [ {description: '3秒前' , timeAgo: moment(now).subtract(3, 'seconds')}, {description: '57秒前' , timeAgo: moment(now).subtract(57, 'seconds')}, {description: '1分7秒前' , timeAgo: moment(now).subtract(1, 'minutes').subtract(7, 'seconds')}, {description: '4分55秒前' , timeAgo: moment(now).subtract(4, 'minutes').subtract(55, 'seconds')}, {description: '17分25秒前' , timeAgo: moment(now).subtract(17, 'minutes').subtract(25, 'seconds')}, {description: '56分2秒前' , timeAgo: moment(now).subtract(56, 'minutes').subtract(2, 'seconds')}, {description: '1時間34分22秒前' , timeAgo: moment(now).subtract(1, 'hours').subtract(34, 'minutes').subtract(22, 'seconds')}, {description: '10時間49分42秒前' , timeAgo: moment(now).subtract(10, 'hours').subtract(49, 'minutes').subtract(42, 'seconds')}, {description: '22時間50分2秒前' , timeAgo: moment(now).subtract(22, 'hours').subtract(50, 'minutes').subtract(2, 'seconds')}, {description: '1日13時間30分52秒前' , timeAgo: moment(now).subtract(1, 'days').subtract(13, 'hours').subtract(30, 'minutes').subtract(52, 'seconds')}, {description: '22日17時間6分11秒前' , timeAgo: moment(now).subtract(22, 'days').subtract(17, 'hours').subtract(6, 'minutes').subtract(11, 'seconds')}, {description: '31日20時間17分55秒前' , timeAgo: moment(now).subtract(31, 'days').subtract(20, 'hours').subtract(17, 'minutes').subtract(55, 'seconds')}, {description: '106日9時間5分1秒前' , timeAgo: moment(now).subtract(106, 'days').subtract(9, 'hours').subtract(5, 'minutes').subtract(1, 'seconds')}, {description: '342日21時間28分14秒前', timeAgo: moment(now).subtract(342, 'days').subtract(21, 'hours').subtract(28, 'minutes').subtract(14, 'seconds')}, {description: '1036日4時間2分53秒前' , timeAgo: moment(now).subtract(1036, 'days').subtract(4, 'hours').subtract(2, 'minutes').subtract(53, 'seconds')}, ] return ( <div className="fromNowTable"> <div className="currentTime">現在時刻: {now.format(DATE_FORMAT)}</div> <table> <thead> <tr> <th>説明</th><th>日時</th><th>moment().fromNow()</th> </tr> </thead> <tbody> {timeAgoArr.map(({description, timeAgo}) => ( <tr> <td className="description">{description}</td> <td>{timeAgo.format(DATE_FORMAT)}</td> <td>{timeAgo.fromNow()}</td> </tr> ))} </tbody> </table> </div> ); } export default App;
実行結果
$ yarn start
http://localhost:3000 を開いて確認します。
それぞれ”5分前”や”2時間前”、”23日前”など表示されることが確かめられました。
あとがき
Ruby on Railsのtime_ago_in_wordsを探していたのですが、全然見つからず苦労しました。危うく自分で実装するところでした。
ちなみにTwitterとfacebookは24時間以内の投稿は、○[分/時間]前、それ以上前だと投稿した日付が表示されます。SNSなどはその方が良いかもしれませんね。