| |
| |
| |
| package timezone |
|
|
| import ( |
| "fmt" |
| "log" |
| "time" |
| ) |
|
|
| var ( |
| |
| location *time.Location |
| |
| tzName string |
| ) |
|
|
| |
| |
| |
| func Init(tz string) error { |
| if tz == "" { |
| tz = "Asia/Shanghai" |
| } |
|
|
| loc, err := time.LoadLocation(tz) |
| if err != nil { |
| return fmt.Errorf("invalid timezone %q: %w", tz, err) |
| } |
|
|
| |
| |
| time.Local = loc |
| location = loc |
| tzName = tz |
|
|
| log.Printf("Timezone initialized: %s (UTC offset: %s)", tz, getUTCOffset(loc)) |
| return nil |
| } |
|
|
| |
| func getUTCOffset(loc *time.Location) string { |
| _, offset := time.Now().In(loc).Zone() |
| hours := offset / 3600 |
| minutes := (offset % 3600) / 60 |
| if minutes < 0 { |
| minutes = -minutes |
| } |
| sign := "+" |
| if hours < 0 { |
| sign = "-" |
| hours = -hours |
| } |
| return fmt.Sprintf("%s%02d:%02d", sign, hours, minutes) |
| } |
|
|
| |
| |
| |
| func Now() time.Time { |
| if location == nil { |
| return time.Now() |
| } |
| return time.Now().In(location) |
| } |
|
|
| |
| func Location() *time.Location { |
| if location == nil { |
| return time.Local |
| } |
| return location |
| } |
|
|
| |
| func Name() string { |
| if tzName == "" { |
| return "Local" |
| } |
| return tzName |
| } |
|
|
| |
| func StartOfDay(t time.Time) time.Time { |
| loc := Location() |
| t = t.In(loc) |
| return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, loc) |
| } |
|
|
| |
| func Today() time.Time { |
| return StartOfDay(Now()) |
| } |
|
|
| |
| func EndOfDay(t time.Time) time.Time { |
| loc := Location() |
| t = t.In(loc) |
| return time.Date(t.Year(), t.Month(), t.Day(), 23, 59, 59, 999999999, loc) |
| } |
|
|
| |
| func StartOfWeek(t time.Time) time.Time { |
| loc := Location() |
| t = t.In(loc) |
| weekday := int(t.Weekday()) |
| if weekday == 0 { |
| weekday = 7 |
| } |
| return time.Date(t.Year(), t.Month(), t.Day()-weekday+1, 0, 0, 0, 0, loc) |
| } |
|
|
| |
| func StartOfMonth(t time.Time) time.Time { |
| loc := Location() |
| t = t.In(loc) |
| return time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, loc) |
| } |
|
|
| |
| func ParseInLocation(layout, value string) (time.Time, error) { |
| return time.ParseInLocation(layout, value, Location()) |
| } |
|
|
| |
| |
| func ParseInUserLocation(layout, value, userTZ string) (time.Time, error) { |
| loc := Location() |
| if userTZ != "" { |
| if userLoc, err := time.LoadLocation(userTZ); err == nil { |
| loc = userLoc |
| } |
| } |
| return time.ParseInLocation(layout, value, loc) |
| } |
|
|
| |
| |
| func NowInUserLocation(userTZ string) time.Time { |
| if userTZ == "" { |
| return Now() |
| } |
| if userLoc, err := time.LoadLocation(userTZ); err == nil { |
| return time.Now().In(userLoc) |
| } |
| return Now() |
| } |
|
|
| |
| |
| func StartOfDayInUserLocation(t time.Time, userTZ string) time.Time { |
| loc := Location() |
| if userTZ != "" { |
| if userLoc, err := time.LoadLocation(userTZ); err == nil { |
| loc = userLoc |
| } |
| } |
| t = t.In(loc) |
| return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, loc) |
| } |
|
|