喜讯!TCMS 官网正式上线!一站式提供企业级定制研发、App 小程序开发、AI 与区块链等全栈软件服务,助力多行业数智转型,欢迎致电:13888011868 QQ 932256355 洽谈合作!
通过以上六种不同编程语言的实现,我们可以看到计算人类可读时间差的核心思路是一致的,只是在语法和时间处理库的使用上有所不同。Python 代码简洁易读,适合快速开发和脚本编写;JavaScript 适合在前端或 Node.js 环境中使用;PHP 常用于服务器端开发;Rust 以其高性能和安全性著称;Go 在并发处理和网络编程方面表现出色;Java 则凭借其跨平台性和强大的生态系统广泛应用于企业级开发。并且这六种语言实现的时间复杂度均为 *O*(1),在处理时间差计算时具有较高的效率,不会随着输入数据的增加而显著增加计算时间。你可以根据自己的项目需求选择合适的语言和实现方式。

在许多应用程序中,展示两个时间点之间的人类可读时间差是一个常见需求,比如社交平台显示消息发布时间、日志系统记录事件间隔等。本文将详细介绍如何使用 Python、JavaScript、PHP、Rust、Go 和 Java 这六种不同的编程语言来实现计算人类可读时间差的功能,同时支持中英文输出,并允许用户选择是否使用 “周” 作为时间单位。
整体的实现思路是先计算两个时间点之间的时间差(以秒为单位),然后根据预设的时间单位阈值,选择最合适的时间单位来表示这个时间差,并将结果格式化为人类可读的字符串。具体步骤如下:
计算时间差 :获取两个时间点之间的秒数差值。
定义时间单位阈值 :定义不同时间单位(如年、月、周、天、小时、分钟)对应的秒数阈值。
选择合适的时间单位 :根据时间差和阈值,选择最合适的时间单位,并计算该单位下的数量。
格式化输出 :根据用户选择的语言(中文或英文),将数量和时间单位组合成人类可读的字符串。
from datetime import datetime
def human_readable_time_diff(
start_time: datetime,
end_time: datetime,
language: str = 'zh',
use_weeks: bool = True
) -> str:
"""
计算两个时间点之间的易读时间差
:param start_time: 起始时间
:param end_time: 结束时间
:param language: 输出语言 ('zh' 中文/'en' 英文)
:param use_weeks: 是否使用"周"作为时间单位
:return: 人类可读的时间差字符串
"""
# 计算两个时间点之间的时间差,结果以秒为单位
delta = end_time - start_time
delta_seconds = abs(delta.total_seconds())
# 定义时间单位及其对应的秒数和阈值
units = [
('year', 365 * 24 * 60 * 60, 365),
('month', 30 * 24 * 60 * 60, 30),
('week', 7 * 24 * 60 * 60, 7) if use_weeks else None,
('day', 24 * 60 * 60, 1),
('hour', 60 * 60, 1/24),
('minute', 60, 1/1440),
]
# 过滤掉为 None 的元素,确保列表中只包含有效的时间单位
units = [u for u in units if u is not None]
# 遍历时间单位列表,找到合适的时间单位
for unit_info in units:
unit, seconds, _ = unit_info
if delta_seconds >= seconds:
# 计算该时间单位下的数量
count = int(delta_seconds // seconds)
return format_output(count, unit, language)
# 如果时间差小于 1 分钟,根据语言输出相应结果
return '刚刚' if language == 'zh' else 'just now'
def format_output(count: int, unit: str, language: str) -> str:
"""格式化输出字符串"""
if language == 'zh':
# 中文时间单位映射
units_zh = {
'year': '年',
'month': '个月',
'week': '周',
'day': '天',
'hour': '小时',
'minute': '分钟'
}
return f"{count}{units_zh[unit]}前"
else:
# 英文时间单位处理单复数
unit_en = unit if count == 1 else f"{unit}s"
return f"{count} {unit_en} ago"
# 使用示例
start = datetime(2024, 3, 20, 10, 0, 0)
end = datetime(2024, 3, 20, 11, 30, 0)
print(human_readable_time_diff(start, end)) # 输出:1小时前
print(human_readable_time_diff(start, end, language='en')) # 输出:1 hour ago
print(human_readable_time_diff(start, end, use_weeks=False)) # 输出:1小时前时间复杂度分析 :Python 实现的时间复杂度为 O (1)。这是因为代码中定义的时间单位列表 units 长度是固定的,不随输入数据的变化而变化。在遍历 units 列表时,最多只会遍历固定的几个元素来找到合适的时间单位,因此时间复杂度是常数级的。
function humanReadableTimeDiff(startTime, endTime, language = 'zh', useWeeks = true) {
// 计算两个时间点之间的时间差,结果以秒为单位
const deltaSeconds = Math.abs((endTime - startTime) / 1000);
// 定义时间单位及其对应的秒数和阈值
const units = [
{ unit: 'year', seconds: 365 * 24 * 60 * 60, threshold: 365 },
{ unit: 'month', seconds: 30 * 24 * 60 * 60, threshold: 30 },
useWeeks ? { unit: 'week', seconds: 7 * 24 * 60 * 60, threshold: 7 } : null,
{ unit: 'day', seconds: 24 * 60 * 60, threshold: 1 },
{ unit: 'hour', seconds: 60 * 60, threshold: 1 / 24 },
{ unit: 'minute', seconds: 60, threshold: 1 / 1440 }
].filter(u => u!== null);
// 遍历时间单位列表,找到合适的时间单位
for (const unitInfo of units) {
if (deltaSeconds >= unitInfo.seconds) {
// 计算该时间单位下的数量
const count = Math.floor(deltaSeconds / unitInfo.seconds);
return formatOutput(count, unitInfo.unit, language);
}
}
// 如果时间差小于 1 分钟,根据语言输出相应结果
return language === 'zh'? '刚刚' : 'just now';
}
function formatOutput(count, unit, language) {
if (language === 'zh') {
// 中文时间单位映射
const unitsZh = {
year: '年',
month: '个月',
week: '周',
day: '天',
hour: '小时',
minute: '分钟'
};
return `${count}${unitsZh[unit]}前`;
} else {
// 英文时间单位处理单复数
const unitEn = count === 1? unit : `${unit}s`;
return `${count} ${unitEn} ago`;
}
}
// 使用示例
const start = new Date(2024, 2, 20, 10, 0, 0);
const end = new Date(2024, 2, 20, 11, 30, 0);
console.log(humanReadableTimeDiff(start, end));
console.log(humanReadableTimeDiff(start, end, 'en'));
console.log(humanReadableTimeDiff(start, end, 'zh', false));时间复杂度分析 :JavaScript 实现的时间复杂度同样为 O (1)。 units 数组的长度是固定的,在遍历该数组寻找合适的时间单位时,操作次数不会随着输入数据的规模增大而增加,所以时间复杂度是常数级的。
另外一个精简版本
// Function to calculate the human-readable time difference
// 人类可读时间差计算函数
function timeAgo(dateString) {
const lastUpdate = new Date(dateString);
const now = new Date();
const diffTime = now - lastUpdate; // Difference in milliseconds
const diffSeconds = Math.floor(diffTime / 1000);
const diffMinutes = Math.floor(diffSeconds / 60);
const diffHours = Math.floor(diffMinutes / 60);
const diffDays = Math.floor(diffHours / 24);
const diffMonths = Math.floor(diffDays / 30);
const diffYears = Math.floor(diffMonths / 12);
if (diffYears > 0) {
return diffYears === 1 ? '1 年以前' : `${diffYears} 年前`;
} else if (diffMonths > 0) {
return diffMonths === 1 ? '1 月前' : `${diffMonths} 月前`;
} else if (diffDays > 0) {
return diffDays === 1 ? '1 天前' : `${diffDays} 天前`;
} else if (diffHours > 0) {
return diffHours === 1 ? '1 小时前' : `${diffHours} 小时前`;
} else if (diffMinutes > 0) {
return diffMinutes === 1 ? '1 分钟前' : `${diffMinutes} 分钟前`;
} else {
return '刚刚';
}
}
<?php
function humanReadableTimeDiff($startTime, $endTime, $language = 'zh', $useWeeks = true) {
// 计算两个时间点之间的时间差,结果以秒为单位
$deltaSeconds = abs(strtotime($endTime) - strtotime($startTime));
// 定义时间单位及其对应的秒数和阈值
$units = [
['unit' => 'year', 'seconds' => 365 * 24 * 60 * 60, 'threshold' => 365],
['unit' => 'month', 'seconds' => 30 * 24 * 60 * 60, 'threshold' => 30],
$useWeeks? ['unit' => 'week', 'seconds' => 7 * 24 * 60 * 60, 'threshold' => 7] : null,
['unit' => 'day', 'seconds' => 24 * 60 * 60, 'threshold' => 1],
['unit' => 'hour', 'seconds' => 60 * 60, 'threshold' => 1 / 24],
['unit' => 'minute', 'seconds' => 60, 'threshold' => 1 / 1440]
];
// 过滤掉为 null 的元素,确保数组中只包含有效的时间单位
$units = array_filter($units);
// 遍历时间单位数组,找到合适的时间单位
foreach ($units as $unitInfo) {
if ($deltaSeconds >= $unitInfo['seconds']) {
// 计算该时间单位下的数量
$count = floor($deltaSeconds / $unitInfo['seconds']);
return formatOutput($count, $unitInfo['unit'], $language);
}
}
// 如果时间差小于 1 分钟,根据语言输出相应结果
return $language === 'zh'? '刚刚' : 'just now';
}
function formatOutput($count, $unit, $language) {
if ($language === 'zh') {
// 中文时间单位映射
$unitsZh = [
'year' => '年',
'month' => '个月',
'week' => '周',
'day' => '天',
'hour' => '小时',
'minute' => '分钟'
];
return $count. $unitsZh[$unit]. '前';
} else {
// 英文时间单位处理单复数
$unitEn = $count === 1? $unit : $unit. 's';
return $count. ' '. $unitEn. ' ago';
}
}
// 使用示例
$start = '2024-03-20 10:00:00';
$end = '2024-03-20 11:30:00';
echo humanReadableTimeDiff($start, $end). "\n";
echo humanReadableTimeDiff($start, $end, 'en'). "\n";
echo humanReadableTimeDiff($start, $end, 'zh', false). "\n";
?>时间复杂度分析 :PHP 实现的时间复杂度为 O (1)。 units 数组的长度是固定的,对其进行过滤和遍历操作的次数都是固定的,不依赖于输入数据的大小,因此时间复杂度为常数级。
use chrono::{DateTime, Utc};
fn human_readable_time_diff(start_time: DateTime<Utc>, end_time: DateTime<Utc>, language: &str, use_weeks: bool) -> String {
// 计算两个时间点之间的时间差,结果以秒为单位
let delta_seconds = (end_time - start_time).num_seconds().abs();
// 定义时间单位及其对应的秒数和阈值
let units = [
("year", 365 * 24 * 60 * 60, 365),
("month", 30 * 24 * 60 * 60, 30),
if use_weeks { Some(("week", 7 * 24 * 60 * 60, 7)) } else { None },
("day", 24 * 60 * 60, 1),
("hour", 60 * 60, 1 / 24),
("minute", 60, 1 / 1440)
].into_iter().filter_map(|x| x).collect::<Vec<_>>();
// 遍历时间单位向量,找到合适的时间单位
for (unit, seconds, _) in units {
if delta_seconds >= *seconds {
// 计算该时间单位下的数量
let count = (delta_seconds / *seconds) as usize;
return format_output(count, unit, language);
}
}
// 如果时间差小于 1 分钟,根据语言输出相应结果
if language == "zh" {
"刚刚".to_string()
} else {
"just now".to_string()
}
}
fn format_output(count: usize, unit: &str, language: &str) -> String {
if language == "zh" {
// 中文时间单位映射
let units_zh = [
("year", "年"),
("month", "个月"),
("week", "周"),
("day", "天"),
("hour", "小时"),
("minute", "分钟")
];
let unit_zh = units_zh.iter().find(|(u, _)| *u == unit).unwrap().1;
format!("{}{}前", count, unit_zh)
} else {
// 英文时间单位处理单复数
let unit_en = if count == 1 {
unit.to_string()
} else {
format!("{}s", unit)
};
format!("{} {} ago", count, unit_en)
}
}
fn main() {
let start = Utc.ymd(2024, 3, 20).and_hms(10, 0, 0);
let end = Utc.ymd(2024, 3, 20).and_hms(11, 30, 0);
println!("{}", human_readable_time_diff(start, end, "zh", true));
println!("{}", human_readable_time_diff(start, end, "en", true));
println!("{}", human_readable_time_diff(start, end, "zh", false));
}时间复杂度分析 :Rust 实现的时间复杂度为 O (1)。 units 数组经过处理后形成的向量长度是固定的,遍历该向量的操作次数不会随着输入数据的变化而变化,所以时间复杂度是常数级的。
package main
import (
"fmt"
"time"
)
func humanReadableTimeDiff(startTime, endTime time.Time, language string, useWeeks bool) string {
// 计算两个时间点之间的时间差,结果以秒为单位
deltaSeconds := int64(endTime.Sub(startTime).Seconds())
if deltaSeconds < 0 {
deltaSeconds = -deltaSeconds
}
// 定义时间单位及其对应的秒数和阈值
units := []struct {
unit string
seconds int64
threshold float64
}{
{"year", 365 * 24 * 60 * 60, 365},
{"month", 30 * 24 * 60 * 60, 30},
{
"week", 7 * 24 * 60 * 60, 7,
},
{"day", 24 * 60 * 60, 1},
{"hour", 60 * 60, 1 / 24},
{"minute", 60, 1 / 1440},
}
// 如果不使用周作为时间单位,从列表中移除周的信息
if!useWeeks {
units = append(units[:2], units[3:]...)
}
// 遍历时间单位切片,找到合适的时间单位
for _, unitInfo := range units {
if deltaSeconds >= unitInfo.seconds {
// 计算该时间单位下的数量
count := deltaSeconds / unitInfo.seconds
return formatOutput(int(count), unitInfo.unit, language)
}
}
// 如果时间差小于 1 分钟,根据语言输出相应结果
if language == "zh" {
return "刚刚"
}
return "just now"
}
func formatOutput(count int, unit string, language string) string {
if language == "zh" {
// 中文时间单位映射
unitsZh := map[string]string{
"year": "年",
"month": "个月",
"week": "周",
"day": "天",
"hour": "小时",
"minute": "分钟",
}
return fmt.Sprintf("%d%s前", count, unitsZh[unit])
}
// 英文时间单位处理单复数
unitEn := unit
if count > 1 {
unitEn = fmt.Sprintf("%ss", unit)
}
return fmt.Sprintf("%d %s ago", count, unitEn)
}
func main() {
start := time.Date(2024, 3, 20, 10, 0, 0, 0, time.UTC)
end := time.Date(2024, 3, 20, 11, 30, 0, 0, time.UTC)
fmt.Println(humanReadableTimeDiff(start, end, "zh", true))
fmt.Println(humanReadableTimeDiff(start, end, "en", true))
fmt.Println(humanReadableTimeDiff(start, end, "zh", false))
}时间复杂度分析 :Go 实现的时间复杂度为 O (1)。 units 切片的长度是固定的,即使在不使用周作为时间单位时进行切片操作,其长度依然是固定的。遍历该切片的操作次数不随输入数据的变化而变化,所以时间复杂度为常数级。
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
class TimeDifferenceFormatter {
public static String humanReadableTimeDiff(LocalDateTime startTime, LocalDateTime endTime, String language, boolean useWeeks) {
// 计算两个时间点之间的时间差,结果以秒为单位
Duration duration = Duration.between(startTime, endTime);
long deltaSeconds = Math.abs(duration.getSeconds());
// 定义时间单位及其对应的秒数和阈值
List<TimeUnitInfo> units = new ArrayList<>();
units.add(new TimeUnitInfo("year", 365 * 24 * 60 * 60, 365));
units.add(new TimeUnitInfo("month", 30 * 24 * 60 * 60, 30));
if (useWeeks) {
units.add(new TimeUnitInfo("week", 7 * 24 * 60 * 60, 7));
}
units.add(new TimeUnitInfo("day", 24 * 60 * 60, 1));
units.add(new TimeUnitInfo("hour", 60 * 60, 1.0 / 24));
units.add(new TimeUnitInfo("minute", 60, 1.0 / (24 * 60)));
// 遍历时间单位列表,找到合适的时间单位
for (TimeUnitInfo unitInfo : units) {
if (deltaSeconds >= unitInfo.seconds) {
// 计算该时间单位下的数量
long count = deltaSeconds / unitInfo.seconds;
return formatOutput(count, unitInfo.unit, language);
}
}
// 如果时间差小于 1 分钟,根据语言输出相应结果
return language.equals("zh")? "刚刚" : "just now";
}
private static String formatOutput(long count, String unit, String language) {
if (language.equals("zh")) {
// 中文时间单位映射
String[] unitsZh = {"年", "个月", "周", "天", "小时", "分钟"};
String[] unitNames = {"year", "month", "week", "day", "hour", "minute"};
for (int i = 0; i < unitNames.length; i++) {
if (unitNames[i].equals(unit)) {
return count + unitsZh[i] + "前";
}
}
} else {
// 英文时间单位处理单复数
String unitEn = count == 1? unit : unit + "s";
return count + " " + unitEn + " ago";
}
return "";
}
static class TimeUnitInfo {
String unit;
long seconds;
double threshold;
TimeUnitInfo(String unit, long seconds, double threshold) {
this.unit = unit;
this.seconds = seconds;
this.threshold = threshold;
}
}
public static void main(String[] args) {
LocalDateTime start = LocalDateTime.of(2024, 3, 20, 10, 0, 0);
LocalDateTime end = LocalDateTime.of(2024, 3, 20, 11, 30, 0);
System.out.println(humanReadableTimeDiff(start, end, "zh", true));
System.out.println(humanReadableTimeDiff(start, end, "en", true));
System.out.println(humanReadableTimeDiff(start, end, "zh", false));
}
}时间复杂度分析 :Java 实现的时间复杂度为 O (1)。 units 列表的长度是固定的,在遍历该列表寻找合适的时间单位时,操作次数不会随着输入数据的规模增大而增加,所以时间复杂度是常数级的。
通过以上六种不同编程语言的实现,我们可以看到计算人类可读时间差的核心思路是一致的,只是在语法和时间处理库的使用上有所不同。Python 代码简洁易读,适合快速开发和脚本编写;JavaScript 适合在前端或 Node.js 环境中使用;PHP 常用于服务器端开发;Rust 以其高性能和安全性著称;Go 在并发处理和网络编程方面表现出色;Java 则凭借其跨平台性和强大的生态系统广泛应用于企业级开发。并且这六种语言实现的时间复杂度均为 O (1),在处理时间差计算时具有较高的效率,不会随着输入数据的增加而显著增加计算时间。你可以根据自己的项目需求选择合适的语言和实现方式。