useTimeAgo

A React Hook that helps format dates into readable "time ago" strings. By default, it updates this "time ago" string every 30 seconds automatically.

Demo

Source
EN Result 1:
2 years ago
EN Result 2:
3 months ago
EN Result 3:
4 days ago
EN Result 4:
5 hours ago
EN Result 5:
6 minutes ago
EN Result 6:
just now
EN Result 7:
in 6 minutes
EN Result 8:
in 5 hours
EN Result 9:
in 4 days
EN Result 10:
in 3 months
EN Result 11:
in 2 years
CN Result 1:
2 年前
CN Result 2:
3 个月前
CN Result 3:
4 天前
CN Result 4:
5 小时前
CN Result 5:
6 分钟前
CN Result 6:
刚刚
CN Result 7:
6 分钟后
CN Result 8:
5 小时后
CN Result 9:
4 天后
CN Result 10:
3 个月后
CN Result 11:
2 年后
CN Traditional Result 1:
2 年前
CN Traditional Result 2:
3 個月前
CN Traditional Result 3:
4 天前
CN Traditional Result 4:
5 小時前
CN Traditional Result 5:
6 分鐘前
CN Traditional Result 6:
剛剛
CN Traditional Result 7:
6 分鐘後
CN Traditional Result 8:
5 小時後
CN Traditional Result 9:
4 天後
CN Traditional Result 10:
3 個月後
CN Traditional Result 11:
2 年後
JP Result 1:
2 年前
JP Result 2:
3 ヶ月前
JP Result 3:
4 日前
JP Result 4:
5 時間前
JP Result 5:
6 分前
JP Result 6:
たった今
JP Result 7:
6 分後
JP Result 8:
5 時間後
JP Result 9:
4 日後
JP Result 10:
3 ヶ月後
JP Result 11:
2 年後

Usage

const timeAgo = useTimeAgo(dateLike, options)

const targetDate = new Date() - 1000 * 60 * 60 * 24 // yesterday

const timeAgo = useTimeAgo(targetDate) 
console.log(timeAgo) // "yesterday"

// Custom language, here using Simplified Chinese
import { CHINESE_MESSAGES } from '@shined/react-use'
const timeAgoInChinese = useTimeAgo(targetDate, { messages: CHINESE_MESSAGES }) 
console.log(timeAgoInChinese) // "昨天"

Currently, Simplified Chinese, Traditional Chinese, English, and Japanese are built in. If needed, you can customize via options.messages. Below is a simple example of formatting in Chinese:

/**
 * Default messages for Chinese Simplified language
 */
export const CHINESE_MESSAGES: TimeAgoMessages<TimeAgoUnitNamesDefault> = {
  justNow: '刚刚',
  past: (n) => (n.match(/\d/) ? `${n}前` : n),
  future: (n) => (n.match(/\d/) ? `${n}后` : n),
  month: (n, past) => (n === 1 ? (past ? '上个月' : '下个月') : `${n} 个月`),
  year: (n, past) => (n === 1 ? (past ? '去年' : '明年') : `${n} 年`),
  day: (n, past) => (n === 1 ? (past ? '昨天' : '明天') : `${n} 天`),
  week: (n, past) => (n === 1 ? (past ? '上周' : '下周') : `${n} 周`),
  hour: (n) => `${n} 小时`,
  minute: (n) => `${n} 分钟`,
  second: (n) => `${n} 秒`,
  invalid: '',
}

Source

Click links below to view source on GitHub.

API

const timeAgo = useTimeAgo(dateLike, options)
const { timeAgo, ...pausable } = useTimeAgo(dateLike, { controls: true, ...otherOptions })

ElementTarget

// Similar to new Date(), 1_612_137_600_000, '2021-01-01', undefined, null
export type DateLike = Date | number | string | undefined | null

Options

export type FormatTimeAgoOptions<UnitNames extends string = TimeAgoUnitNamesDefault> = {
  /**
   * Maximum unit (millisecond difference), beyond which will display the full date instead of relative time
   *
   * @defaultValue undefined
   */
  max?: UnitNames | number
  /**
   * Formatter for the full date
   */
  fullDateFormatter?: TimeAgeFullDateFormatter
  /**
   * Messages for formatting strings
   */
  messages?: TimeAgoMessages<UnitNames>
  /**
   * The smallest displayed time unit (default is minute)
   *
   * @defaultValue false
   */
  showSecond?: boolean
  /**
   * Rounding method applied.
   *
   * @defaultValue 'round'
   */
  rounding?: 'round' | 'ceil' | 'floor' | number
  /**
   * Custom units
   */
  units?: TimeAgoUnit<UnitNames>[]
}

export interface UseTimeAgoOptions<Controls extends boolean, UnitNames extends string = TimeAgoUnitNamesDefault>
  extends FormatTimeAgoOptions<UnitNames> {
  /**
   * Exposes additional controls
   *
   * @defaultValue false
   */
  controls?: Controls
  /**
   * Update interval, set to 0 to disable automatic updates
   *
   * @defaultValue 30_000
   */
  updateInterval?: number
}

Returns

The return value includes a Pausable instance that can be paused and resumed.

For more details, please refer to Pausable.

export type UseTimeAgoReturns<Controls extends boolean = false> = Controls extends true
  ? { timeAgo: string } & Pausable
  : string