喜讯!TCMS 官网正式上线!一站式提供企业级定制研发、App 小程序开发、AI 与区块链等全栈软件服务,助力多行业数智转型,欢迎致电:13888011868  QQ 932256355 洽谈合作!

多语言实现人类可读时间差计算 -- python, go, php, rust, js代码实现

2025-05-03 27分钟阅读时长

通过以上六种不同编程语言的实现,我们可以看到计算人类可读时间差的核心思路是一致的,只是在语法和时间处理库的使用上有所不同。Python 代码简洁易读,适合快速开发和脚本编写;JavaScript 适合在前端或 Node.js 环境中使用;PHP 常用于服务器端开发;Rust 以其高性能和安全性著称;Go 在并发处理和网络编程方面表现出色;Java 则凭借其跨平台性和强大的生态系统广泛应用于企业级开发。并且这六种语言实现的时间复杂度均为 *O*(1),在处理时间差计算时具有较高的效率,不会随着输入数据的增加而显著增加计算时间。你可以根据自己的项目需求选择合适的语言和实现方式。

mplementing-Human-Readable-Time-Difference-Calculation-in-Multiple-Languages-
 

简介

在许多应用程序中,展示两个时间点之间的人类可读时间差是一个常见需求,比如社交平台显示消息发布时间、日志系统记录事件间隔等。本文将详细介绍如何使用 Python、JavaScript、PHP、Rust、Go 和 Java 这六种不同的编程语言来实现计算人类可读时间差的功能,同时支持中英文输出,并允许用户选择是否使用 “周” 作为时间单位。

实现思路

整体的实现思路是先计算两个时间点之间的时间差(以秒为单位),然后根据预设的时间单位阈值,选择最合适的时间单位来表示这个时间差,并将结果格式化为人类可读的字符串。具体步骤如下:

  1. 计算时间差 :获取两个时间点之间的秒数差值。

  2. 定义时间单位阈值 :定义不同时间单位(如年、月、周、天、小时、分钟)对应的秒数阈值。

  3. 选择合适的时间单位 :根据时间差和阈值,选择最合适的时间单位,并计算该单位下的数量。

  4. 格式化输出 :根据用户选择的语言(中文或英文),将数量和时间单位组合成人类可读的字符串。

 

Python 代码实现

 

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 列表时,最多只会遍历固定的几个元素来找到合适的时间单位,因此时间复杂度是常数级的。

JavaScript 实现

 

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 实现

 

<?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 数组的长度是固定的,对其进行过滤和遍历操作的次数都是固定的,不依赖于输入数据的大小,因此时间复杂度为常数级。

Rust 实现

 

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 数组经过处理后形成的向量长度是固定的,遍历该向量的操作次数不会随着输入数据的变化而变化,所以时间复杂度是常数级的。

Go 实现

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 切片的长度是固定的,即使在不使用周作为时间单位时进行切片操作,其长度依然是固定的。遍历该切片的操作次数不随输入数据的变化而变化,所以时间复杂度为常数级。

Java 实现

 

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

新闻通讯图片
主图标
新闻通讯

订阅我们的新闻通讯

在下方输入邮箱地址后,点击订阅按钮即可完成订阅,同时代表您同意我们的条款与条件。

启用 Cookie,可让您在本网站获得更流畅的使用体验 Cookie政策