init
This commit is contained in:
@@ -0,0 +1,213 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"goravel/app/utils"
|
||||
"time"
|
||||
|
||||
"github.com/goravel/framework/contracts/http"
|
||||
"github.com/goravel/framework/facades"
|
||||
"github.com/goravel/framework/support/carbon"
|
||||
"github.com/goravel/framework/support/str"
|
||||
)
|
||||
|
||||
// GetCurrentTimezone 获取当前请求的时区
|
||||
// 优先从请求头 X-Timezone 或 Timezone 获取
|
||||
// 如果请求头没有或时区无效,使用配置的默认时区
|
||||
func GetCurrentTimezone(ctx http.Context) string {
|
||||
// 优先从 X-Timezone 请求头获取
|
||||
timezone := ctx.Request().Header("X-Timezone", "")
|
||||
if timezone == "" {
|
||||
// 尝试从 Timezone 请求头获取
|
||||
timezone = ctx.Request().Header("Timezone", "")
|
||||
}
|
||||
if timezone == "" {
|
||||
// 尝试从查询参数获取
|
||||
timezone = ctx.Request().Input("timezone")
|
||||
}
|
||||
|
||||
// 如果从请求中获取到了时区,规范化并返回
|
||||
if timezone != "" {
|
||||
return NormalizeTimezone(timezone)
|
||||
}
|
||||
|
||||
// 如果都没有,使用配置的默认时区
|
||||
defaultTimezone := facades.Config().GetString("app.timezone", carbon.UTC)
|
||||
return NormalizeTimezone(defaultTimezone)
|
||||
}
|
||||
|
||||
// isValidTimezone 验证时区是否有效
|
||||
func isValidTimezone(timezone string) bool {
|
||||
if timezone == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
// 尝试加载时区
|
||||
_, err := time.LoadLocation(timezone)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// NormalizeTimezone 规范化时区名称(处理常见别名)
|
||||
func NormalizeTimezone(timezone string) string {
|
||||
timezone = str.Of(timezone).Trim().String()
|
||||
if str.Of(timezone).IsEmpty() {
|
||||
return carbon.UTC
|
||||
}
|
||||
|
||||
// 转换为标准时区名称
|
||||
timezoneMap := map[string]string{
|
||||
"UTC": "UTC",
|
||||
"GMT": "UTC",
|
||||
"PST": "America/Los_Angeles",
|
||||
"PDT": "America/Los_Angeles",
|
||||
"EST": "America/New_York",
|
||||
"EDT": "America/New_York",
|
||||
"CST": "America/Chicago",
|
||||
"CDT": "America/Chicago",
|
||||
"MST": "America/Denver",
|
||||
"MDT": "America/Denver",
|
||||
"Beijing": "Asia/Shanghai",
|
||||
"Shanghai": "Asia/Shanghai",
|
||||
"Hong Kong": "Asia/Hong_Kong",
|
||||
"Tokyo": "Asia/Tokyo",
|
||||
"Seoul": "Asia/Seoul",
|
||||
"Singapore": "Asia/Singapore",
|
||||
"London": "Europe/London",
|
||||
"Paris": "Europe/Paris",
|
||||
"Berlin": "Europe/Berlin",
|
||||
"Moscow": "Europe/Moscow",
|
||||
"Sydney": "Australia/Sydney",
|
||||
"Melbourne": "Australia/Melbourne",
|
||||
}
|
||||
|
||||
if normalized, ok := timezoneMap[timezone]; ok {
|
||||
return normalized
|
||||
}
|
||||
|
||||
// 如果时区有效,直接返回
|
||||
if isValidTimezone(timezone) {
|
||||
return timezone
|
||||
}
|
||||
|
||||
// 默认返回 UTC
|
||||
return carbon.UTC
|
||||
}
|
||||
|
||||
// ConvertTimeToTimezone 将时间字符串转换为指定时区
|
||||
// 返回转换后的时间字符串
|
||||
func ConvertTimeToTimezone(timeStr string, timezone string) string {
|
||||
if timeStr == "" {
|
||||
return ""
|
||||
}
|
||||
// 规范化时区
|
||||
timezone = NormalizeTimezone(timezone)
|
||||
|
||||
// 解析时间字符串
|
||||
dt := carbon.Parse(timeStr)
|
||||
if dt.IsZero() {
|
||||
return timeStr
|
||||
}
|
||||
// 转换时区并返回格式化的字符串
|
||||
return dt.SetTimezone(timezone).ToDateTimeString()
|
||||
}
|
||||
|
||||
// ConvertTimeByContext 根据请求头中的时区转换时间字符串
|
||||
// 返回转换后的时间字符串
|
||||
func ConvertTimeByContext(ctx http.Context, timeStr string) string {
|
||||
if timeStr == "" {
|
||||
return ""
|
||||
}
|
||||
timezone := GetCurrentTimezone(ctx)
|
||||
return ConvertTimeToTimezone(timeStr, timezone)
|
||||
}
|
||||
|
||||
// ConvertTimeToUTC 将本地时区的时间字符串转换为 UTC 时间字符串(用于数据库查询)
|
||||
// timeStr: 前端传入的时间字符串(本地时区格式,如 "2025-11-25 14:00:00")
|
||||
// ctx: 请求上下文,用于获取当前时区
|
||||
// 返回: UTC 时间字符串(如 "2025-11-25 06:00:00")
|
||||
func ConvertTimeToUTC(ctx http.Context, timeStr string) string {
|
||||
if timeStr == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 获取当前请求的时区
|
||||
timezone := GetCurrentTimezone(ctx)
|
||||
|
||||
// 如果已经是 UTC,直接返回
|
||||
if timezone == carbon.UTC || timezone == "UTC" {
|
||||
return timeStr
|
||||
}
|
||||
|
||||
// 加载时区
|
||||
targetLoc, err := time.LoadLocation(timezone)
|
||||
if err != nil {
|
||||
// 如果时区无效,假设是 UTC
|
||||
return timeStr
|
||||
}
|
||||
utcLoc, _ := time.LoadLocation("UTC")
|
||||
|
||||
// 解析时间字符串(假设是本地时区格式)
|
||||
// 尝试多种格式
|
||||
formats := []string{
|
||||
utils.DateTimeFormat,
|
||||
utils.DateTimeFormatT,
|
||||
utils.DateTimeFormatMs,
|
||||
utils.DateTimeFormatTZ,
|
||||
time.RFC3339,
|
||||
}
|
||||
|
||||
var t time.Time
|
||||
var parseErr error
|
||||
for _, format := range formats {
|
||||
t, parseErr = time.ParseInLocation(format, timeStr, targetLoc)
|
||||
if parseErr == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if parseErr != nil {
|
||||
// 如果所有格式都失败,尝试使用 carbon 解析
|
||||
dt := carbon.Parse(timeStr)
|
||||
if dt.IsZero() {
|
||||
return timeStr
|
||||
}
|
||||
// 假设解析的时间是本地时区,转换为 UTC
|
||||
return dt.SetTimezone(carbon.UTC).ToDateTimeString()
|
||||
}
|
||||
|
||||
// 转换为 UTC 并格式化
|
||||
return t.In(utcLoc).Format(utils.DateTimeFormat)
|
||||
}
|
||||
|
||||
// GetTimeQueryParam 获取并转换时间查询参数(统一处理时间查询)
|
||||
// 自动将前端传入的本地时区时间转换为 UTC 时间用于数据库查询
|
||||
// 支持常见的时间查询参数名称:start_time, end_time, created_at_start, created_at_end, updated_at_start, updated_at_end
|
||||
func GetTimeQueryParam(ctx http.Context, paramName string) string {
|
||||
timeStr := ctx.Request().Query(paramName, "")
|
||||
if timeStr == "" {
|
||||
return ""
|
||||
}
|
||||
return ConvertTimeToUTC(ctx, timeStr)
|
||||
}
|
||||
|
||||
// FormatTimeWithTimezone 使用指定时区格式化 time.Time
|
||||
func FormatTimeWithTimezone(t time.Time, timezone string) string {
|
||||
if t.IsZero() {
|
||||
return ""
|
||||
}
|
||||
if timezone == "" {
|
||||
timezone = "UTC"
|
||||
}
|
||||
loc, err := time.LoadLocation(timezone)
|
||||
if err != nil {
|
||||
return t.Format("2006-01-02 15:04:05")
|
||||
}
|
||||
return t.In(loc).Format("2006-01-02 15:04:05")
|
||||
}
|
||||
|
||||
// FormatCarbonWithTimezone 使用指定时区格式化 Carbon 时间
|
||||
func FormatCarbonWithTimezone(t *carbon.DateTime, timezone string) string {
|
||||
if t == nil || t.IsZero() {
|
||||
return ""
|
||||
}
|
||||
return FormatTimeWithTimezone(t.StdTime(), timezone)
|
||||
}
|
||||
Reference in New Issue
Block a user