First commit

This commit is contained in:
shaw
2025-12-18 13:50:39 +08:00
parent 569f4882e5
commit 642842c29e
218 changed files with 86902 additions and 0 deletions

View File

@@ -0,0 +1,124 @@
// Package timezone provides global timezone management for the application.
// Similar to PHP's date_default_timezone_set, this package allows setting
// a global timezone that affects all time.Now() calls.
package timezone
import (
"fmt"
"log"
"time"
)
var (
// location is the global timezone location
location *time.Location
// tzName stores the timezone name for logging/debugging
tzName string
)
// Init initializes the global timezone setting.
// This should be called once at application startup.
// Example timezone values: "Asia/Shanghai", "America/New_York", "UTC"
func Init(tz string) error {
if tz == "" {
tz = "Asia/Shanghai" // Default timezone
}
loc, err := time.LoadLocation(tz)
if err != nil {
return fmt.Errorf("invalid timezone %q: %w", tz, err)
}
// Set the global Go time.Local to our timezone
// This affects time.Now() throughout the application
time.Local = loc
location = loc
tzName = tz
log.Printf("Timezone initialized: %s (UTC offset: %s)", tz, getUTCOffset(loc))
return nil
}
// getUTCOffset returns the current UTC offset for a location
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)
}
// Now returns the current time in the configured timezone.
// This is equivalent to time.Now() after Init() is called,
// but provided for explicit timezone-aware code.
func Now() time.Time {
if location == nil {
return time.Now()
}
return time.Now().In(location)
}
// Location returns the configured timezone location.
func Location() *time.Location {
if location == nil {
return time.Local
}
return location
}
// Name returns the configured timezone name.
func Name() string {
if tzName == "" {
return "Local"
}
return tzName
}
// StartOfDay returns the start of the given day (00:00:00) in the configured timezone.
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)
}
// Today returns the start of today (00:00:00) in the configured timezone.
func Today() time.Time {
return StartOfDay(Now())
}
// EndOfDay returns the end of the given day (23:59:59.999999999) in the configured timezone.
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)
}
// StartOfWeek returns the start of the week (Monday 00:00:00) for the given time.
func StartOfWeek(t time.Time) time.Time {
loc := Location()
t = t.In(loc)
weekday := int(t.Weekday())
if weekday == 0 {
weekday = 7 // Sunday is day 7
}
return time.Date(t.Year(), t.Month(), t.Day()-weekday+1, 0, 0, 0, 0, loc)
}
// StartOfMonth returns the start of the month (1st day 00:00:00) for the given time.
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)
}
// ParseInLocation parses a time string in the configured timezone.
func ParseInLocation(layout, value string) (time.Time, error) {
return time.ParseInLocation(layout, value, Location())
}