diff --git a/protocols/utils.proto b/protocols/utils.proto index e735d731..4a96debe 100644 --- a/protocols/utils.proto +++ b/protocols/utils.proto @@ -4,12 +4,15 @@ option go_package = "github.com/movsb/taoblog/proto"; message FormatTimeRequest { repeated int32 unix = 1; + // 设备时区。 + string device = 2; } message FormatTimeResponse { message Formatted { string friendly = 1; - string rfc3339 = 2; + string server = 3; + string device = 4; } repeated Formatted formatted = 1; } diff --git a/service/utils.go b/service/utils.go index 74d39b8f..6638022d 100644 --- a/service/utils.go +++ b/service/utils.go @@ -7,14 +7,17 @@ import ( "sync/atomic" "time" + _ "time/tzdata" + "github.com/movsb/taoblog/modules/auth" "github.com/movsb/taoblog/modules/dialers" "github.com/movsb/taoblog/modules/notify" "github.com/movsb/taoblog/protocols/go/proto" + "github.com/phuslu/lru" "github.com/xeonx/timeago" ) -var fixedZone = time.FixedZone(``, 8*60*60) +var fixedZone = time.Now().Local().Location() type Utils struct { proto.UnimplementedUtilsServer @@ -22,11 +25,14 @@ type Utils struct { instantNotifier notify.InstantNotifier RemoteDialer atomic.Pointer[dialers.RemoteDialerManager] + + timeLocations *lru.TTLCache[string, *time.Location] } func NewUtils(instantNotifier notify.InstantNotifier) *Utils { u := &Utils{ instantNotifier: instantNotifier, + timeLocations: lru.NewTTLCache[string, *time.Location](16), } u.RemoteDialer.Store(nil) return u @@ -34,11 +40,25 @@ func NewUtils(instantNotifier notify.InstantNotifier) *Utils { func (u *Utils) FormatTime(ctx context.Context, in *proto.FormatTimeRequest) (*proto.FormatTimeResponse, error) { formatted := make([]*proto.FormatTimeResponse_Formatted, len(in.Unix)) - for i, u := range in.Unix { + for i, ts := range in.Unix { r := proto.FormatTimeResponse_Formatted{} - t := time.Unix(int64(u), 0).In(fixedZone) + t := time.Unix(int64(ts), 0) r.Friendly = timeago.Chinese.Format(t) - r.Rfc3339 = t.Format(time.RFC3339) + r.Server = t.In(fixedZone).Format(time.RFC3339) + + if in.Device != `` { + loc, err, _ := u.timeLocations.GetOrLoad(ctx, in.Device, func(ctx context.Context, s string) (*time.Location, time.Duration, error) { + loc, err := time.LoadLocation(s) + // log.Println(`加载时区:`, s, loc, err) + return loc, time.Hour, err + }) + if err != nil { + log.Println(err) + } else { + // log.Println(`时区:`, loc) + r.Device = t.In(loc).Format(time.RFC3339) + } + } formatted[i] = &r } return &proto.FormatTimeResponse{ diff --git a/theme/blog/statics/scripts/comment.js b/theme/blog/statics/scripts/comment.js index 07ed046a..e15508b8 100644 --- a/theme/blog/statics/scripts/comment.js +++ b/theme/blog/statics/scripts/comment.js @@ -54,50 +54,6 @@ document.write(function(){/* */}.toString().slice(14,-3)); -class TimeWithZone { - constructor(timestamp, zone) { - const now = new Date(); - if (typeof timestamp != 'number') { - timestamp = now.getTime() / 1000; - zone = TimeWithZone.getTimezone(); - } else if (typeof zone != 'string' || zone == '') { - zone = TimeWithZone.getTimezone(); - } - this._timestamp = timestamp; - this._zone = zone; - } - - get time() { return this._timestamp; } - get zone() { return this._zone; } - - format() { - const options = { - timeZone: this._zone, - timeZoneName: 'longOffset', - year: "numeric", - month: "2-digit", - day: "2-digit", - hour: "2-digit", - minute: "2-digit", - second: "2-digit", - hourCycle: 'h24', - } - return new Intl.DateTimeFormat(navigator.language, options).format(new Date(this._timestamp)); - } - - toJSON() { - return new Date(this._timestamp).toJSON(); - } - - static getTimezone() { - try { - return Intl.DateTimeFormat().resolvedOptions().timeZone; - } catch { - return ''; - } - } -} - class CommentAPI { constructor(postID) { @@ -734,12 +690,9 @@ class Comment { let info = ''; if (loggedin) { info = `编号:${cmt.id} -作者:${cmt.author} 邮箱:${cmt.email} -网址:${cmt.url} 地址:${cmt.ip} 位置:${cmt.geo_location} -日期:${date.format()} `; } @@ -767,7 +720,7 @@ class Comment {
${cmt.source_type === 'markdown' ? `