69 lines
2.0 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 mysql
import (
"context"
"strings"
"time"
)
const (
// StatTZUTC 是历史默认口径,保留它可以让旧接口、旧报表和跨服务 UTC 统计规则继续稳定工作。
StatTZUTC = "UTC"
// StatTZAsiaShanghai 是 Databi 需要的中国自然日口径;中国当前无夏令时,固定 +08:00 能避免容器缺 tzdata 时切日失败。
StatTZAsiaShanghai = "Asia/Shanghai"
)
var asiaShanghaiLocation = time.FixedZone(StatTZAsiaShanghai, 8*60*60)
type statDayScope struct {
tz string
day string
}
type statTZScopeContextKey struct{}
// WithStatTZScope 限制当前聚合只写一个 stat_tz实时消费不使用它回灌任务用它避免重放历史事件时污染 UTC 口径。
func WithStatTZScope(ctx context.Context, statTZ string) context.Context {
return context.WithValue(ctx, statTZScopeContextKey{}, normalizeStatTZ(statTZ))
}
func normalizeStatTZ(value string) string {
switch strings.TrimSpace(value) {
case StatTZAsiaShanghai:
return StatTZAsiaShanghai
case StatTZUTC, "":
return StatTZUTC
default:
return StatTZUTC
}
}
func statLocation(statTZ string) *time.Location {
if normalizeStatTZ(statTZ) == StatTZAsiaShanghai {
return asiaShanghaiLocation
}
return time.UTC
}
func statDayIn(ms int64, statTZ string) string {
return time.UnixMilli(ms).In(statLocation(statTZ)).Format("2006-01-02")
}
func statDayScopes(ms int64) []statDayScope {
// 同一条业务事实必须一次事务内写出两份读模型UTC 行维持历史聚合Asia/Shanghai 行给中国自然日大屏使用。
return []statDayScope{
{tz: StatTZUTC, day: statDayIn(ms, StatTZUTC)},
{tz: StatTZAsiaShanghai, day: statDayIn(ms, StatTZAsiaShanghai)},
}
}
func statDayScopesFromContext(ctx context.Context, ms int64) []statDayScope {
if ctx != nil {
if statTZ, ok := ctx.Value(statTZScopeContextKey{}).(string); ok {
statTZ = normalizeStatTZ(statTZ)
return []statDayScope{{tz: statTZ, day: statDayIn(ms, statTZ)}}
}
}
return statDayScopes(ms)
}