XTime Guide - zhoudm1743/go-util GitHub Wiki
XTime 是 Go-Util 的核心时间处理工具,提供强大而直观的时间操作API,让日期时间处理变得简单而精确。
🚀 特性亮点
- 🔗 链式调用: 流畅的方法链,提高代码可读性
- 🌍 时区支持: 完整的时区处理和转换功能
- 📅 格式化: 丰富的时间格式化选项
- ⚡ 高性能: 优化的时间计算和缓存机制
- 🎯 精确计算: 精确的时间差值和日期运算
- 🔧 易扩展: 支持自定义格式和解析规则
📦 基础用法
创建 XTime 对象
import util "github.com/zhoudm1743/go-util"
// 当前时间
now := util.Now() // 当前时间
utcNow := util.NowUTC() // UTC当前时间
// 从时间戳创建
timestamp := util.FromTimestamp(1640995200) // 2022-01-01 00:00:00 UTC
milliTime := util.FromMillisecond(1640995200000)
// 从字符串解析
parsed := util.ParseTime("2023-01-01 15:30:00", "2006-01-02 15:04:05")
iso8601 := util.ParseISO8601("2023-01-01T15:30:00Z")
rfc3339 := util.ParseRFC3339("2023-01-01T15:30:00+08:00")
// 从日期构建
date := util.Date(2023, 1, 1, 15, 30, 0, 0)
dateUTC := util.DateUTC(2023, 1, 1, 15, 30, 0, 0)
// 从现有time.Time创建
t := time.Now()
xtime := util.TimeFrom(t)
基础信息获取
now := util.Now()
// 时间组件
fmt.Println(now.Year()) // 2023
fmt.Println(now.Month()) // 1
fmt.Println(now.Day()) // 15
fmt.Println(now.Hour()) // 14
fmt.Println(now.Minute()) // 30
fmt.Println(now.Second()) // 45
fmt.Println(now.Millisecond()) // 123
fmt.Println(now.Microsecond()) // 123456
fmt.Println(now.Nanosecond()) // 123456789
// 星期和年份信息
fmt.Println(now.Weekday()) // Monday
fmt.Println(now.WeekdayInt()) // 1 (周一为1)
fmt.Println(now.DayOfYear()) // 15
fmt.Println(now.WeekOfYear()) // 3
// 时间戳
fmt.Println(now.Timestamp()) // 1674657045
fmt.Println(now.TimestampMilli()) // 1674657045123
fmt.Println(now.TimestampMicro()) // 1674657045123456
fmt.Println(now.TimestampNano()) // 1674657045123456789
// 转换为原生time.Time
nativeTime := now.Time()
📅 时间格式化
预定义格式
now := util.Now()
// 常用格式
fmt.Println(now.Format()) // 2023-01-15 14:30:45 (默认格式)
fmt.Println(now.FormatDate()) // 2023-01-15
fmt.Println(now.FormatTime()) // 14:30:45
fmt.Println(now.FormatDateTime()) // 2023-01-15 14:30:45
// 国际标准格式
fmt.Println(now.FormatISO8601()) // 2023-01-15T14:30:45Z
fmt.Println(now.FormatRFC3339()) // 2023-01-15T14:30:45+08:00
fmt.Println(now.FormatRFC822()) // 15 Jan 23 14:30 CST
// 中文格式
fmt.Println(now.FormatChinese()) // 2023年01月15日 14时30分45秒
fmt.Println(now.FormatChineseDate()) // 2023年01月15日
fmt.Println(now.FormatChineseTime()) // 14时30分45秒
自定义格式
now := util.Now()
// 自定义格式字符串
fmt.Println(now.FormatCustom("2006/01/02 15:04:05")) // 2023/01/15 14:30:45
fmt.Println(now.FormatCustom("Jan 2, 2006")) // Jan 15, 2023
fmt.Println(now.FormatCustom("Monday, 2 January 2006")) // Sunday, 15 January 2023
// 链式格式化
formatted := now.
ToUTC(). // 转换为UTC
FormatCustom("2006-01-02T15:04:05Z") // 格式化
// 带时区的格式化
beijing := now.InTimezone("Asia/Shanghai")
fmt.Println(beijing.FormatWithTimezone("Asia/Shanghai", "2006-01-02 15:04:05 MST"))
相对时间格式
now := util.Now()
past := now.AddDays(-3)
future := now.AddHours(2)
// 相对时间描述
fmt.Println(past.FormatRelative()) // "3 days ago"
fmt.Println(future.FormatRelative()) // "in 2 hours"
// 人性化时间差
fmt.Println(past.Humanize()) // "3天前"
fmt.Println(future.Humanize()) // "2小时后"
// 智能格式化
fmt.Println(past.FormatSmart()) // 根据时间差自动选择格式
⏱️ 时间运算
加减运算
now := util.Now()
// 时间单位加减
later := now.
AddYears(1). // 加1年
AddMonths(2). // 加2个月
AddDays(15). // 加15天
AddHours(3). // 加3小时
AddMinutes(30). // 加30分钟
AddSeconds(45) // 加45秒
// 减法运算
earlier := now.
SubYears(1). // 减1年
SubMonths(2). // 减2个月
SubDays(15). // 减15天
SubHours(3). // 减3小时
SubMinutes(30). // 减30分钟
SubSeconds(45) // 减45秒
// 时间段加减
duration := time.Hour * 2 + time.Minute * 30
withDuration := now.Add(duration)
withoutDuration := now.Sub(duration)
// 链式运算
result := now.
AddDays(7). // 加一周
SetHour(9). // 设置为9点
SetMinute(0). // 设置为0分
SetSecond(0) // 设置为0秒
设置时间组件
now := util.Now()
// 设置具体时间组件
modified := now.
SetYear(2024). // 设置年份
SetMonth(12). // 设置月份
SetDay(25). // 设置日期
SetHour(18). // 设置小时
SetMinute(30). // 设置分钟
SetSecond(0). // 设置秒数
SetMillisecond(0) // 设置毫秒
// 批量设置
dateTime := now.SetDate(2024, 12, 25) // 设置日期
timeOnly := now.SetTime(18, 30, 0) // 设置时间
complete := now.SetDateTime(2024, 12, 25, 18, 30, 0) // 设置完整时间
🌍 时区处理
时区转换
now := util.Now()
// 转换到不同时区
utc := now.ToUTC() // 转换为UTC
local := now.ToLocal() // 转换为本地时区
beijing := now.InTimezone("Asia/Shanghai") // 转换为北京时间
tokyo := now.InTimezone("Asia/Tokyo") // 转换为东京时间
newYork := now.InTimezone("America/New_York") // 转换为纽约时间
// 时区偏移
offset8 := now.InOffset(8) // UTC+8
offsetMinus5 := now.InOffset(-5) // UTC-5
// 获取时区信息
fmt.Println(now.TimezoneName()) // "CST"
fmt.Println(now.TimezoneOffset()) // 28800 (秒)
fmt.Println(now.TimezoneAbbr()) // "CST"
时区信息
now := util.Now()
// 检查时区
fmt.Println(now.IsUTC()) // false
fmt.Println(now.IsLocal()) // true
fmt.Println(now.IsDST()) // 是否夏令时
// 时区列表
timezones := util.CommonTimezones() // 常用时区列表
asian := util.AsianTimezones() // 亚洲时区
american := util.AmericanTimezones() // 美洲时区
// 时区验证
isValid := util.IsValidTimezone("Asia/Shanghai") // true
📊 时间比较
基础比较
t1 := util.ParseTime("2023-01-15 10:00:00", "2006-01-02 15:04:05")
t2 := util.ParseTime("2023-01-15 14:00:00", "2006-01-02 15:04:05")
// 比较操作
fmt.Println(t1.Equal(t2)) // false
fmt.Println(t1.Before(t2)) // true
fmt.Println(t1.After(t2)) // false
// 比较方法
fmt.Println(t1.Compare(t2)) // -1 (小于)
fmt.Println(t2.Compare(t1)) // 1 (大于)
fmt.Println(t1.Compare(t1)) // 0 (等于)
// 范围检查
start := util.ParseTime("2023-01-01", "2006-01-02")
end := util.ParseTime("2023-01-31", "2006-01-02")
current := util.ParseTime("2023-01-15", "2006-01-02")
fmt.Println(current.Between(start, end)) // true
fmt.Println(current.IsBetween(start, end)) // true (别名)
时间差计算
start := util.ParseTime("2023-01-01 10:00:00", "2006-01-02 15:04:05")
end := util.ParseTime("2023-01-15 14:30:45", "2006-01-02 15:04:05")
// 计算差值
duration := end.DiffTime(start) // time.Duration
fmt.Println(duration) // 350h30m45s
// 具体单位的差值
fmt.Println(end.DiffDays(start)) // 14
fmt.Println(end.DiffHours(start)) // 350.5125
fmt.Println(end.DiffMinutes(start)) // 21030.75
fmt.Println(end.DiffSeconds(start)) // 1261845
// 绝对差值
fmt.Println(start.AbsDiff(end)) // 总是正数
fmt.Println(start.AbsDiffDays(end)) // 14
// 人性化差值描述
fmt.Println(end.DiffForHumans(start)) // "14天后"
📅 日期操作
日期边界
now := util.Now()
// 时间边界
startOfDay := now.StartOfDay() // 当天开始 00:00:00
endOfDay := now.EndOfDay() // 当天结束 23:59:59
startOfWeek := now.StartOfWeek() // 本周开始 (周一)
endOfWeek := now.EndOfWeek() // 本周结束 (周日)
startOfMonth := now.StartOfMonth() // 本月开始
endOfMonth := now.EndOfMonth() // 本月结束
startOfYear := now.StartOfYear() // 本年开始
endOfYear := now.EndOfYear() // 本年结束
// 下一个边界
nextDay := now.NextDay() // 明天同一时间
nextWeek := now.NextWeek() // 下周同一时间
nextMonth := now.NextMonth() // 下月同一天
nextYear := now.NextYear() // 明年同一天
// 上一个边界
prevDay := now.PrevDay() // 昨天同一时间
prevWeek := now.PrevWeek() // 上周同一时间
prevMonth := now.PrevMonth() // 上月同一天
prevYear := now.PrevYear() // 去年同一天
日期判断
now := util.Now()
target := util.ParseTime("2023-01-15", "2006-01-02")
// 时间单位判断
fmt.Println(now.IsToday()) // true/false
fmt.Println(target.IsYesterday()) // true/false
fmt.Println(target.IsTomorrow()) // true/false
fmt.Println(now.IsThisWeek()) // true
fmt.Println(now.IsThisMonth()) // true
fmt.Println(now.IsThisYear()) // true
// 相对判断
fmt.Println(target.IsPast()) // 是否是过去时间
fmt.Println(target.IsFuture()) // 是否是未来时间
fmt.Println(target.IsCurrentWeek()) // 是否在当前周
fmt.Println(target.IsCurrentMonth()) // 是否在当前月
fmt.Println(target.IsCurrentYear()) // 是否在当前年
// 特殊日期判断
fmt.Println(now.IsLeapYear()) // 是否闰年
fmt.Println(now.IsWeekend()) // 是否周末
fmt.Println(now.IsWeekday()) // 是否工作日
⏰ 高级功能
时间范围
// 创建时间范围
start := util.ParseTime("2023-01-01", "2006-01-02")
end := util.ParseTime("2023-01-31", "2006-01-02")
timeRange := util.NewTimeRange(start, end)
// 范围操作
fmt.Println(timeRange.Duration()) // 时间跨度
fmt.Println(timeRange.Contains(util.Now())) // 是否包含指定时间
fmt.Println(timeRange.IsValid()) // 范围是否有效
// 范围迭代
timeRange.EachDay(func(day *util.XTime) bool {
fmt.Println(day.FormatDate())
return true // 继续迭代
})
// 按小时迭代
timeRange.EachHour(func(hour *util.XTime) bool {
fmt.Println(hour.FormatDateTime())
return true
})
时间解析
// 智能解析
auto1 := util.ParseAuto("2023-01-15") // 自动识别格式
auto2 := util.ParseAuto("2023/01/15 14:30")
auto3 := util.ParseAuto("Jan 15, 2023")
// 多格式尝试解析
formats := []string{
"2006-01-02",
"2006/01/02",
"01/02/2006",
"Jan 2, 2006",
}
parsed := util.ParseWithFormats("01/15/2023", formats...)
// 松散解析
loose := util.ParseLoose("next monday") // 解析相对时间
flexible := util.ParseFlexible("in 2 hours") // 解析时间短语
// 批量解析
timeStrings := []string{
"2023-01-01", "2023-01-02", "2023-01-03",
}
times := util.ParseBatch(timeStrings, "2006-01-02")
时间缓存和性能
// 时间缓存
cache := util.NewTimeCache(time.Minute * 5) // 5分钟缓存
now := cache.Now() // 缓存的当前时间
// 高性能时间戳
timestamp := util.FastTimestamp() // 快速获取时间戳
milliTs := util.FastTimestampMilli() // 快速获取毫秒时间戳
// 时间池
pool := util.NewTimePool()
t := pool.Get() // 从池中获取
// 使用完后
pool.Put(t) // 归还到池中
// 批量操作
times := util.NewTimeBatch()
times.Add(util.Now())
times.Add(util.Now().AddDays(1))
results := times.FormatAll("2006-01-02") // 批量格式化
🔧 实际应用场景
日志和监控
// 日志时间戳
func LogWithTimestamp(level, message string) {
timestamp := util.Now().FormatCustom("2006-01-02 15:04:05.000")
fmt.Printf("[%s] %s: %s\n", timestamp, level, message)
}
// 性能监控
type PerformanceMonitor struct {
startTime *util.XTime
}
func (pm *PerformanceMonitor) Start() {
pm.startTime = util.Now()
}
func (pm *PerformanceMonitor) End() time.Duration {
return util.Now().DiffTime(pm.startTime)
}
// 请求耗时统计
func TrackRequestTime(handler http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
start := util.Now()
handler(w, r)
duration := util.Now().DiffTime(start)
log.Printf("Request %s took %v", r.URL.Path, duration)
}
}
任务调度
// 定时任务
type ScheduledTask struct {
name string
nextRun *util.XTime
interval time.Duration
}
func (st *ScheduledTask) ShouldRun() bool {
return util.Now().After(st.nextRun)
}
func (st *ScheduledTask) UpdateNextRun() {
st.nextRun = util.Now().Add(st.interval)
}
// 日程管理
type Calendar struct {
events map[string]*util.XTime
}
func (c *Calendar) AddEvent(name string, when *util.XTime) {
c.events[name] = when
}
func (c *Calendar) GetUpcomingEvents(within time.Duration) []string {
var upcoming []string
cutoff := util.Now().Add(within)
for name, eventTime := range c.events {
if eventTime.Between(util.Now(), cutoff) {
upcoming = append(upcoming, name)
}
}
return upcoming
}
// 工作日计算
func CalculateWorkdays(start, end *util.XTime) int {
workdays := 0
current := start.Clone()
for current.Before(end) || current.Equal(end) {
if current.IsWeekday() {
workdays++
}
current = current.AddDays(1)
}
return workdays
}
数据分析
// 时间序列数据处理
type TimeSeriesData struct {
Timestamp *util.XTime
Value float64
}
func AnalyzeTimeSeries(data []TimeSeriesData) map[string]interface{} {
if len(data) == 0 {
return nil
}
// 按日分组
dailyData := make(map[string][]float64)
for _, point := range data {
day := point.Timestamp.FormatDate()
dailyData[day] = append(dailyData[day], point.Value)
}
// 统计分析
analysis := make(map[string]interface{})
analysis["total_days"] = len(dailyData)
analysis["date_range"] = map[string]string{
"start": data[0].Timestamp.FormatDate(),
"end": data[len(data)-1].Timestamp.FormatDate(),
}
return analysis
}
// 活跃时间分析
func AnalyzeUserActivity(loginTimes []*util.XTime) map[int]int {
hourlyActivity := make(map[int]int)
for _, loginTime := range loginTimes {
hour := loginTime.Hour()
hourlyActivity[hour]++
}
return hourlyActivity
}
// 业务时间计算
func CalculateBusinessHours(start, end *util.XTime) time.Duration {
if start.IsWeekend() || end.IsWeekend() {
return 0 // 周末不计入业务时间
}
// 业务时间: 9:00-18:00
businessStart := start.SetTime(9, 0, 0)
businessEnd := start.SetTime(18, 0, 0)
actualStart := start
if start.Before(businessStart) {
actualStart = businessStart
}
actualEnd := end
if end.After(businessEnd) {
actualEnd = businessEnd
}
if actualEnd.Before(actualStart) {
return 0
}
return actualEnd.DiffTime(actualStart)
}
国际化时间
// 多语言时间格式
type LocalizedTime struct {
time *util.XTime
locale string
}
func NewLocalizedTime(t *util.XTime, locale string) *LocalizedTime {
return &LocalizedTime{time: t, locale: locale}
}
func (lt *LocalizedTime) Format() string {
switch lt.locale {
case "zh-CN":
return lt.time.FormatChinese()
case "en-US":
return lt.time.FormatCustom("January 2, 2006 3:04 PM")
case "ja-JP":
return lt.time.FormatCustom("2006年1月2日 15時04分")
default:
return lt.time.Format()
}
}
// 时区会议调度
func ScheduleGlobalMeeting(baseTime *util.XTime, timezones []string) map[string]string {
schedule := make(map[string]string)
for _, tz := range timezones {
localTime := baseTime.InTimezone(tz)
schedule[tz] = localTime.FormatCustom("Jan 2, 15:04 MST")
}
return schedule
}
// 营业时间检查
func IsBusinessOpen(timezone string) bool {
localTime := util.Now().InTimezone(timezone)
// 营业时间: 周一至周五 9:00-18:00
if localTime.IsWeekend() {
return false
}
hour := localTime.Hour()
return hour >= 9 && hour < 18
}
📊 性能基准
基准测试结果
操作类型 性能指标
Now() 纳秒级
Format操作 微秒级
时区转换 微秒级
时间解析 微秒级
时间运算 纳秒级
比较操作 纳秒级
性能优化技巧
// ✅ 使用缓存减少系统调用
cache := util.NewTimeCache(time.Second)
now := cache.Now() // 缓存1秒内的当前时间
// ✅ 预编译时间格式
var customFormat = "2006-01-02 15:04:05"
formatted := now.FormatCustom(customFormat)
// ✅ 批量操作
times := []string{"2023-01-01", "2023-01-02", "2023-01-03"}
parsed := util.ParseBatch(times, "2006-01-02")
// ✅ 对象池复用
pool := util.NewTimePool()
t := pool.Get()
defer pool.Put(t)
// ❌ 避免频繁的时区转换
for i := 0; i < 1000; i++ {
_ = now.InTimezone("Asia/Shanghai") // 每次都转换
}
// ✅ 一次转换,多次使用
beijingTime := now.InTimezone("Asia/Shanghai")
for i := 0; i < 1000; i++ {
_ = beijingTime.Format() // 使用已转换的时间
}
🎯 最佳实践
1. 时区处理
// ✅ 明确指定时区
utcTime := util.NowUTC()
localTime := utcTime.InTimezone("Asia/Shanghai")
// ✅ 存储时使用UTC,显示时转换为本地时区
func SaveEvent(eventTime *util.XTime) {
utcTime := eventTime.ToUTC()
// 存储 utcTime 到数据库
}
func DisplayEvent(utcTime *util.XTime, userTimezone string) string {
localTime := utcTime.InTimezone(userTimezone)
return localTime.FormatDateTime()
}
// ❌ 避免混用不同时区的时间
2. 性能优化
// ✅ 使用适当的精度
timestamp := util.FastTimestamp() // 秒级精度
milliTs := util.FastTimestampMilli() // 毫秒级精度
// ✅ 缓存频繁使用的时间
startOfToday := util.Now().StartOfDay()
// ✅ 批量处理
var times []*util.XTime
// ... 收集时间
formatted := util.FormatBatch(times, "2006-01-02")
3. 错误处理
// ✅ 安全解析时间
parsed, err := util.ParseSafe("2023-13-01", "2006-01-02")
if err != nil {
log.Printf("时间解析失败: %v", err)
return
}
// ✅ 使用默认值
parsed := util.ParseOrDefault("invalid", "2006-01-02", util.Now())
// ✅ 验证时间范围
if !timeValue.Between(minTime, maxTime) {
return errors.New("时间超出有效范围")
}
🔗 相关资源
💬 获取帮助
如果您在使用 XTime 时遇到问题:
- 🔍 查看FAQ - 常见时间处理问题
- 🐛 报告问题 - Bug反馈
- 💡 功能建议 - 新功能讨论
- 📧 邮件支持 - [email protected]
🎉 现在您已经掌握了 XTime 的强大功能,开始在项目中使用这些优雅的时间操作吧!