TypeScript中的相对时间解析

Published on
Published on
/4 mins read/---

一个简单的JavaScript工具函数,用于解析相对时间。以人类可读的格式显示自给定过去日期/时间以来的时间。

time-ago.ts
function is(interval: number, cycle: number) {
  return cycle >= interval ? Math.floor(cycle / interval) : 0
}
 
export function getTimeAgo(time: string | number | Date, now = Date.now()): string {
  if (typeof time === 'string' || time instanceof Date) {
    time = new Date(time).getTime()
  }
 
  let secs = (now - time) / 1000
  let mins = is(60, secs)
  let hours = is(60, mins)
  let days = is(24, hours)
  let weeks = is(7, days)
  let months = is(30, days)
  let years = is(12, months)
 
  let amt = years
  let cycle = 'year'
 
  if (secs <= 1) {
    return 'just now'
  }
  if (years > 0) {
    amt = years
    cycle = 'year'
  } else if (months > 0) {
    amt = months
    cycle = 'month'
  } else if (weeks > 0) {
    amt = weeks
    cycle = 'week'
  } else if (days > 0) {
    amt = days
    cycle = 'day'
  } else if (hours > 0) {
    amt = hours
    cycle = 'hour'
  } else if (mins > 0) {
    amt = mins
    cycle = 'minute'
  } else if (secs > 0) {
    amt = secs
    cycle = 'second'
  }
 
  let v = Math.floor(amt)
 
  return `${v === 1 ? (amt === hours ? 'an' : 'a') : v} ${cycle}${v > 1 ? 's' : ''} ago`
}

使用示例:

example.ts
const MARCH_10_2025 = new Date('2025-03-10').getTime()
 
getTimeAgo(MARCH_10_2025, MARCH_10_2025) // 'just now'
getTimeAgo('2025-03-08', MARCH_10_2025) // '2 days ago'
getTimeAgo('2025-03-02', MARCH_10_2025) // 'a week ago'

中文版本

如果需要中文输出,可以修改函数:

time-ago-zh.ts
function is(interval: number, cycle: number) {
  return cycle >= interval ? Math.floor(cycle / interval) : 0
}
 
export function getTimeAgoChinese(time: string | number | Date, now = Date.now()): string {
  if (typeof time === 'string' || time instanceof Date) {
    time = new Date(time).getTime()
  }
 
  let secs = (now - time) / 1000
  let mins = is(60, secs)
  let hours = is(60, mins)
  let days = is(24, hours)
  let weeks = is(7, days)
  let months = is(30, days)
  let years = is(12, months)
 
  if (secs <= 1) {
    return '刚刚'
  }
  if (years > 0) {
    return `${Math.floor(years)}年前`
  } else if (months > 0) {
    return `${Math.floor(months)}个月前`
  } else if (weeks > 0) {
    return `${Math.floor(weeks)}周前`
  } else if (days > 0) {
    return `${Math.floor(days)}天前`
  } else if (hours > 0) {
    return `${Math.floor(hours)}小时前`
  } else if (mins > 0) {
    return `${Math.floor(mins)}分钟前`
  } else {
    return `${Math.floor(secs)}秒前`
  }
}

使用场景

这个工具函数适用于:

  • 社交媒体应用:显示帖子发布时间
  • 评论系统:显示评论时间
  • 博客文章:显示文章发布时间
  • 聊天应用:显示消息时间
  • 活动日志:显示操作时间

扩展功能

支持未来时间

export function getRelativeTime(time: string | number | Date, now = Date.now()): string {
  if (typeof time === 'string' || time instanceof Date) {
    time = new Date(time).getTime()
  }
 
  const diff = time - now
  const isPast = diff < 0
  const secs = Math.abs(diff) / 1000
 
  // ... 相同的计算逻辑 ...
 
  const suffix = isPast ? '前' : '后'
  // 返回相对时间字符串
}

更精确的时间计算

// 考虑闰年和每月天数不同的精确计算
export function getPreciseTimeAgo(time: string | number | Date): string {
  // 使用更精确的日期计算逻辑
}

Happy time-ago parsing!