Files
go-common/datetime/datetime.go

359 lines
9.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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...)
}