package datetime import ( "fmt" "time" ) // TimeZone 时区常量 const ( UTC = "UTC" AsiaShanghai = "Asia/Shanghai" AmericaNewYork = "America/New_York" EuropeLondon = "Europe/London" AsiaTokyo = "Asia/Tokyo" ) // DefaultTimeZone 默认时区 var DefaultTimeZone = UTC // SetDefaultTimeZone 设置默认时区 func SetDefaultTimeZone(timezone string) error { _, err := time.LoadLocation(timezone) if err != nil { return fmt.Errorf("invalid timezone: %w", err) } DefaultTimeZone = timezone return nil } // GetLocation 获取时区Location对象 func GetLocation(timezone string) (*time.Location, error) { if timezone == "" { timezone = DefaultTimeZone } return time.LoadLocation(timezone) } // Now 获取当前时间(使用指定时区) func Now(timezone ...string) time.Time { tz := DefaultTimeZone if len(timezone) > 0 && timezone[0] != "" { tz = timezone[0] } loc, err := GetLocation(tz) if err != nil { // 如果时区无效,使用UTC loc, _ = time.LoadLocation(UTC) } return time.Now().In(loc) } // Parse 解析时间字符串 // layout: 时间格式,如 "2006-01-02 15:04:05" // value: 时间字符串 // timezone: 时区,如果为空则使用默认时区 func Parse(layout, value string, timezone ...string) (time.Time, error) { tz := DefaultTimeZone if len(timezone) > 0 && timezone[0] != "" { tz = timezone[0] } loc, err := GetLocation(tz) if err != nil { return time.Time{}, fmt.Errorf("invalid timezone: %w", err) } t, err := time.ParseInLocation(layout, value, loc) if err != nil { return time.Time{}, fmt.Errorf("failed to parse time: %w", err) } return t, nil } // Format 格式化时间 // t: 时间对象 // layout: 时间格式,如 "2006-01-02 15:04:05" // timezone: 时区,如果为空则使用时间对象本身的时区 func Format(t time.Time, layout string, timezone ...string) string { if len(timezone) > 0 && timezone[0] != "" { loc, err := GetLocation(timezone[0]) if err == nil { t = t.In(loc) } } return t.Format(layout) } // ToTimezone 将时间转换到指定时区 func ToTimezone(t time.Time, timezone string) (time.Time, error) { loc, err := GetLocation(timezone) if err != nil { return time.Time{}, fmt.Errorf("invalid timezone: %w", err) } return t.In(loc), nil } // CommonLayouts 常用时间格式 var CommonLayouts = struct { DateTime string DateTimeSec string Date string Time string TimeSec string ISO8601 string RFC3339 string RFC3339Nano string Unix string }{ DateTime: "2006-01-02 15:04", DateTimeSec: "2006-01-02 15:04:05", Date: "2006-01-02", Time: "15:04", TimeSec: "15:04:05", ISO8601: "2006-01-02T15:04:05Z07:00", RFC3339: time.RFC3339, RFC3339Nano: time.RFC3339Nano, Unix: "unix", } // FormatDateTime 格式化日期时间(2006-01-02 15:04:05) func FormatDateTime(t time.Time, timezone ...string) string { return Format(t, CommonLayouts.DateTimeSec, timezone...) } // FormatDate 格式化日期(2006-01-02) func FormatDate(t time.Time, timezone ...string) string { return Format(t, CommonLayouts.Date, timezone...) } // FormatTime 格式化时间(15:04:05) func FormatTime(t time.Time, timezone ...string) string { return Format(t, CommonLayouts.TimeSec, timezone...) } // ParseDateTime 解析日期时间字符串(2006-01-02 15:04:05) func ParseDateTime(value string, timezone ...string) (time.Time, error) { return Parse(CommonLayouts.DateTimeSec, value, timezone...) } // ParseDate 解析日期字符串(2006-01-02) func ParseDate(value string, timezone ...string) (time.Time, error) { return Parse(CommonLayouts.Date, value, timezone...) } // ToUnix 转换为Unix时间戳 func ToUnix(t time.Time) int64 { return t.Unix() } // FromUnix 从Unix时间戳创建时间 func FromUnix(sec int64, timezone ...string) time.Time { t := time.Unix(sec, 0) if len(timezone) > 0 && timezone[0] != "" { loc, err := GetLocation(timezone[0]) if err == nil { t = t.In(loc) } } return t } // ToUnixMilli 转换为Unix毫秒时间戳 func ToUnixMilli(t time.Time) int64 { return t.UnixMilli() } // FromUnixMilli 从Unix毫秒时间戳创建时间 func FromUnixMilli(msec int64, timezone ...string) time.Time { t := time.UnixMilli(msec) if len(timezone) > 0 && timezone[0] != "" { loc, err := GetLocation(timezone[0]) if err == nil { t = t.In(loc) } } return t } // AddDays 添加天数 func AddDays(t time.Time, days int) time.Time { return t.AddDate(0, 0, days) } // AddMonths 添加月数 func AddMonths(t time.Time, months int) time.Time { return t.AddDate(0, months, 0) } // AddYears 添加年数 func AddYears(t time.Time, years int) time.Time { return t.AddDate(years, 0, 0) } // StartOfDay 获取一天的开始时间(00:00:00) func StartOfDay(t time.Time, timezone ...string) time.Time { tz := DefaultTimeZone if len(timezone) > 0 && timezone[0] != "" { tz = timezone[0] } loc, err := GetLocation(tz) if err != nil { loc, _ = time.LoadLocation(UTC) } t = t.In(loc) year, month, day := t.Date() return time.Date(year, month, day, 0, 0, 0, 0, loc) } // EndOfDay 获取一天的结束时间(23:59:59.999999999) func EndOfDay(t time.Time, timezone ...string) time.Time { tz := DefaultTimeZone if len(timezone) > 0 && timezone[0] != "" { tz = timezone[0] } loc, err := GetLocation(tz) if err != nil { loc, _ = time.LoadLocation(UTC) } t = t.In(loc) year, month, day := t.Date() return time.Date(year, month, day, 23, 59, 59, 999999999, loc) } // StartOfMonth 获取月份的开始时间 func StartOfMonth(t time.Time, timezone ...string) time.Time { tz := DefaultTimeZone if len(timezone) > 0 && timezone[0] != "" { tz = timezone[0] } loc, err := GetLocation(tz) if err != nil { loc, _ = time.LoadLocation(UTC) } t = t.In(loc) year, month, _ := t.Date() return time.Date(year, month, 1, 0, 0, 0, 0, loc) } // EndOfMonth 获取月份的结束时间 func EndOfMonth(t time.Time, timezone ...string) time.Time { tz := DefaultTimeZone if len(timezone) > 0 && timezone[0] != "" { tz = timezone[0] } loc, err := GetLocation(tz) if err != nil { loc, _ = time.LoadLocation(UTC) } t = t.In(loc) year, month, _ := t.Date() // 获取下个月的第一天,然后减去1纳秒 nextMonth := time.Date(year, month+1, 1, 0, 0, 0, 0, loc) return nextMonth.Add(-time.Nanosecond) } // StartOfYear 获取年份的开始时间 func StartOfYear(t time.Time, timezone ...string) time.Time { tz := DefaultTimeZone if len(timezone) > 0 && timezone[0] != "" { tz = timezone[0] } loc, err := GetLocation(tz) if err != nil { loc, _ = time.LoadLocation(UTC) } t = t.In(loc) year, _, _ := t.Date() return time.Date(year, 1, 1, 0, 0, 0, 0, loc) } // EndOfYear 获取年份的结束时间 func EndOfYear(t time.Time, timezone ...string) time.Time { tz := DefaultTimeZone if len(timezone) > 0 && timezone[0] != "" { tz = timezone[0] } loc, err := GetLocation(tz) if err != nil { loc, _ = time.LoadLocation(UTC) } t = t.In(loc) year, _, _ := t.Date() return time.Date(year, 12, 31, 23, 59, 59, 999999999, loc) } // DiffDays 计算两个时间之间的天数差 func DiffDays(t1, t2 time.Time) int { return int(t2.Sub(t1).Hours() / 24) } // DiffHours 计算两个时间之间的小时差 func DiffHours(t1, t2 time.Time) int64 { return int64(t2.Sub(t1).Hours()) } // DiffMinutes 计算两个时间之间的分钟差 func DiffMinutes(t1, t2 time.Time) int64 { return int64(t2.Sub(t1).Minutes()) } // DiffSeconds 计算两个时间之间的秒数差 func DiffSeconds(t1, t2 time.Time) int64 { return int64(t2.Sub(t1).Seconds()) } // ToUTC 将时间转换为UTC时间 // t: 时间对象(可以是任意时区) // 返回: UTC时间 func ToUTC(t time.Time) time.Time { return t.UTC() } // ToUTCFromTimezone 从指定时区转换为UTC时间 // t: 时间对象(会被视为指定时区的时间) // timezone: 源时区 // 返回: UTC时间 // 注意:此方法假设时间对象t表示的是指定时区的本地时间,然后转换为UTC func ToUTCFromTimezone(t time.Time, timezone string) (time.Time, error) { loc, err := GetLocation(timezone) if err != nil { return time.Time{}, fmt.Errorf("invalid timezone: %w", err) } // 将时间视为指定时区的本地时间,然后转换为UTC // 首先将时间转换到指定时区,然后转换为UTC localTime := time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), loc) return localTime.UTC(), nil } // ParseToUTC 解析时间字符串并转换为UTC时间 // layout: 时间格式,如 "2006-01-02 15:04:05" // value: 时间字符串 // timezone: 源时区,如果为空则使用默认时区 // 返回: UTC时间 func ParseToUTC(layout, value string, timezone ...string) (time.Time, error) { t, err := Parse(layout, value, timezone...) if err != nil { return time.Time{}, err } return t.UTC(), nil } // ParseDateTimeToUTC 解析日期时间字符串并转换为UTC时间(便捷方法) // value: 时间字符串(格式: 2006-01-02 15:04:05) // timezone: 源时区,如果为空则使用默认时区 // 返回: UTC时间 func ParseDateTimeToUTC(value string, timezone ...string) (time.Time, error) { return ParseToUTC(CommonLayouts.DateTimeSec, value, timezone...) } // ParseDateToUTC 解析日期字符串并转换为UTC时间(便捷方法) // value: 日期字符串(格式: 2006-01-02) // timezone: 源时区,如果为空则使用默认时区 // 返回: UTC时间(当天的00:00:00 UTC时间) func ParseDateToUTC(value string, timezone ...string) (time.Time, error) { return ParseToUTC(CommonLayouts.Date, value, timezone...) }