喜讯!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),在处理时间差计算时具有较高的效率,不会随着输入数据的增加而显著增加计算时间。你可以根据自己的项目需求选择合适的语言和实现方式。