patch time: time.Format
This commit is contained in:
@@ -611,7 +611,7 @@ func (t Time) GoString() string {
|
|||||||
buf = append(buf, ')')
|
buf = append(buf, ')')
|
||||||
return string(buf)
|
return string(buf)
|
||||||
*/
|
*/
|
||||||
panic("todo")
|
panic("todo: time.GoString")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format returns a textual representation of the time value formatted according
|
// Format returns a textual representation of the time value formatted according
|
||||||
@@ -637,7 +637,6 @@ func (t Time) Format(layout string) string {
|
|||||||
// AppendFormat is like Format but appends the textual
|
// AppendFormat is like Format but appends the textual
|
||||||
// representation to b and returns the extended buffer.
|
// representation to b and returns the extended buffer.
|
||||||
func (t Time) AppendFormat(b []byte, layout string) []byte {
|
func (t Time) AppendFormat(b []byte, layout string) []byte {
|
||||||
/*
|
|
||||||
// Optimize for RFC3339 as it accounts for over half of all representations.
|
// Optimize for RFC3339 as it accounts for over half of all representations.
|
||||||
switch layout {
|
switch layout {
|
||||||
case RFC3339:
|
case RFC3339:
|
||||||
@@ -647,12 +646,9 @@ func (t Time) AppendFormat(b []byte, layout string) []byte {
|
|||||||
default:
|
default:
|
||||||
return t.appendFormat(b, layout)
|
return t.appendFormat(b, layout)
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
panic("todo")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Time) appendFormat(b []byte, layout string) []byte {
|
func (t Time) appendFormat(b []byte, layout string) []byte {
|
||||||
/*
|
|
||||||
var (
|
var (
|
||||||
name, offset, abs = t.locabs()
|
name, offset, abs = t.locabs()
|
||||||
|
|
||||||
@@ -818,8 +814,6 @@ func (t Time) appendFormat(b []byte, layout string) []byte {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return b
|
return b
|
||||||
*/
|
|
||||||
panic("todo")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var errBad = errors.New("bad value for field") // placeholder not passed to user
|
var errBad = errors.New("bad value for field") // placeholder not passed to user
|
||||||
@@ -1023,7 +1017,7 @@ func Parse(layout, value string) (Time, error) {
|
|||||||
}
|
}
|
||||||
return parse(layout, value, UTC, Local)
|
return parse(layout, value, UTC, Local)
|
||||||
*/
|
*/
|
||||||
panic("todo")
|
panic("todo: time.Parse")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseInLocation is like Parse but differs in two important ways.
|
// ParseInLocation is like Parse but differs in two important ways.
|
||||||
@@ -1041,7 +1035,7 @@ func ParseInLocation(layout, value string, loc *Location) (Time, error) {
|
|||||||
}
|
}
|
||||||
return parse(layout, value, loc, loc)
|
return parse(layout, value, loc, loc)
|
||||||
*/
|
*/
|
||||||
panic("todo")
|
panic("todo: time.ParseInLocation")
|
||||||
}
|
}
|
||||||
|
|
||||||
func parse(layout, value string, defaultLocation, local *Location) (Time, error) {
|
func parse(layout, value string, defaultLocation, local *Location) (Time, error) {
|
||||||
@@ -1413,7 +1407,7 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error)
|
|||||||
// Otherwise, fall back to default.
|
// Otherwise, fall back to default.
|
||||||
return Date(year, Month(month), day, hour, min, sec, nsec, defaultLocation), nil
|
return Date(year, Month(month), day, hour, min, sec, nsec, defaultLocation), nil
|
||||||
*/
|
*/
|
||||||
panic("todo")
|
panic("todo: time.parse")
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseTimeZone parses a time zone string and returns its length. Time zones
|
// parseTimeZone parses a time zone string and returns its length. Time zones
|
||||||
|
|||||||
188
internal/lib/time/format_rfc3339.go
Normal file
188
internal/lib/time/format_rfc3339.go
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
// Copyright 2022 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package time
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
// RFC 3339 is the most commonly used format.
|
||||||
|
//
|
||||||
|
// It is implicitly used by the Time.(Marshal|Unmarshal)(Text|JSON) methods.
|
||||||
|
// Also, according to analysis on https://go.dev/issue/52746,
|
||||||
|
// RFC 3339 accounts for 57% of all explicitly specified time formats,
|
||||||
|
// with the second most popular format only being used 8% of the time.
|
||||||
|
// The overwhelming use of RFC 3339 compared to all other formats justifies
|
||||||
|
// the addition of logic to optimize formatting and parsing.
|
||||||
|
|
||||||
|
func (t Time) appendFormatRFC3339(b []byte, nanos bool) []byte {
|
||||||
|
_, offset, abs := t.locabs()
|
||||||
|
|
||||||
|
// Format date.
|
||||||
|
year, month, day, _ := absDate(abs, true)
|
||||||
|
b = appendInt(b, year, 4)
|
||||||
|
b = append(b, '-')
|
||||||
|
b = appendInt(b, int(month), 2)
|
||||||
|
b = append(b, '-')
|
||||||
|
b = appendInt(b, day, 2)
|
||||||
|
|
||||||
|
b = append(b, 'T')
|
||||||
|
|
||||||
|
// Format time.
|
||||||
|
hour, min, sec := absClock(abs)
|
||||||
|
b = appendInt(b, hour, 2)
|
||||||
|
b = append(b, ':')
|
||||||
|
b = appendInt(b, min, 2)
|
||||||
|
b = append(b, ':')
|
||||||
|
b = appendInt(b, sec, 2)
|
||||||
|
|
||||||
|
if nanos {
|
||||||
|
std := stdFracSecond(stdFracSecond9, 9, '.')
|
||||||
|
b = appendNano(b, t.Nanosecond(), std)
|
||||||
|
}
|
||||||
|
|
||||||
|
if offset == 0 {
|
||||||
|
return append(b, 'Z')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format zone.
|
||||||
|
zone := offset / 60 // convert to minutes
|
||||||
|
if zone < 0 {
|
||||||
|
b = append(b, '-')
|
||||||
|
zone = -zone
|
||||||
|
} else {
|
||||||
|
b = append(b, '+')
|
||||||
|
}
|
||||||
|
b = appendInt(b, zone/60, 2)
|
||||||
|
b = append(b, ':')
|
||||||
|
b = appendInt(b, zone%60, 2)
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t Time) appendStrictRFC3339(b []byte) ([]byte, error) {
|
||||||
|
n0 := len(b)
|
||||||
|
b = t.appendFormatRFC3339(b, true)
|
||||||
|
|
||||||
|
// Not all valid Go timestamps can be serialized as valid RFC 3339.
|
||||||
|
// Explicitly check for these edge cases.
|
||||||
|
// See https://go.dev/issue/4556 and https://go.dev/issue/54580.
|
||||||
|
num2 := func(b []byte) byte { return 10*(b[0]-'0') + (b[1] - '0') }
|
||||||
|
switch {
|
||||||
|
case b[n0+len("9999")] != '-': // year must be exactly 4 digits wide
|
||||||
|
return b, errors.New("year outside of range [0,9999]")
|
||||||
|
case b[len(b)-1] != 'Z':
|
||||||
|
c := b[len(b)-len("Z07:00")]
|
||||||
|
if ('0' <= c && c <= '9') || num2(b[len(b)-len("07:00"):]) >= 24 {
|
||||||
|
return b, errors.New("timezone hour outside of range [0,23]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseRFC3339[bytes []byte | string](s bytes, local *Location) (Time, bool) {
|
||||||
|
// parseUint parses s as an unsigned decimal integer and
|
||||||
|
// verifies that it is within some range.
|
||||||
|
// If it is invalid or out-of-range,
|
||||||
|
// it sets ok to false and returns the min value.
|
||||||
|
ok := true
|
||||||
|
parseUint := func(s bytes, min, max int) (x int) {
|
||||||
|
for _, c := range []byte(s) {
|
||||||
|
if c < '0' || '9' < c {
|
||||||
|
ok = false
|
||||||
|
return min
|
||||||
|
}
|
||||||
|
x = x*10 + int(c) - '0'
|
||||||
|
}
|
||||||
|
if x < min || max < x {
|
||||||
|
ok = false
|
||||||
|
return min
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the date and time.
|
||||||
|
if len(s) < len("2006-01-02T15:04:05") {
|
||||||
|
return Time{}, false
|
||||||
|
}
|
||||||
|
year := parseUint(s[0:4], 0, 9999) // e.g., 2006
|
||||||
|
month := parseUint(s[5:7], 1, 12) // e.g., 01
|
||||||
|
day := parseUint(s[8:10], 1, daysIn(Month(month), year)) // e.g., 02
|
||||||
|
hour := parseUint(s[11:13], 0, 23) // e.g., 15
|
||||||
|
min := parseUint(s[14:16], 0, 59) // e.g., 04
|
||||||
|
sec := parseUint(s[17:19], 0, 59) // e.g., 05
|
||||||
|
if !ok || !(s[4] == '-' && s[7] == '-' && s[10] == 'T' && s[13] == ':' && s[16] == ':') {
|
||||||
|
return Time{}, false
|
||||||
|
}
|
||||||
|
s = s[19:]
|
||||||
|
|
||||||
|
// Parse the fractional second.
|
||||||
|
var nsec int
|
||||||
|
if len(s) >= 2 && s[0] == '.' && isDigit(s, 1) {
|
||||||
|
n := 2
|
||||||
|
for ; n < len(s) && isDigit(s, n); n++ {
|
||||||
|
}
|
||||||
|
nsec, _, _ = parseNanoseconds(s, n)
|
||||||
|
s = s[n:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the time zone.
|
||||||
|
t := Date(year, Month(month), day, hour, min, sec, nsec, UTC)
|
||||||
|
if len(s) != 1 || s[0] != 'Z' {
|
||||||
|
if len(s) != len("-07:00") {
|
||||||
|
return Time{}, false
|
||||||
|
}
|
||||||
|
hr := parseUint(s[1:3], 0, 23) // e.g., 07
|
||||||
|
mm := parseUint(s[4:6], 0, 59) // e.g., 00
|
||||||
|
if !ok || !((s[0] == '-' || s[0] == '+') && s[3] == ':') {
|
||||||
|
return Time{}, false
|
||||||
|
}
|
||||||
|
zoneOffset := (hr*60 + mm) * 60
|
||||||
|
if s[0] == '-' {
|
||||||
|
zoneOffset *= -1
|
||||||
|
}
|
||||||
|
t.addSec(-int64(zoneOffset))
|
||||||
|
|
||||||
|
// Use local zone with the given offset if possible.
|
||||||
|
if _, offset, _, _, _ := local.lookup(t.unixSec()); offset == zoneOffset {
|
||||||
|
t.setLoc(local)
|
||||||
|
} else {
|
||||||
|
t.setLoc(FixedZone("", zoneOffset))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return t, true
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseStrictRFC3339(b []byte) (Time, error) {
|
||||||
|
t, ok := parseRFC3339(b, Local)
|
||||||
|
if !ok {
|
||||||
|
t, err := Parse(RFC3339, string(b))
|
||||||
|
if err != nil {
|
||||||
|
return Time{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// The parse template syntax cannot correctly validate RFC 3339.
|
||||||
|
// Explicitly check for cases that Parse is unable to validate for.
|
||||||
|
// See https://go.dev/issue/54580.
|
||||||
|
num2 := func(b []byte) byte { return 10*(b[0]-'0') + (b[1] - '0') }
|
||||||
|
switch {
|
||||||
|
// TODO(https://go.dev/issue/54580): Strict parsing is disabled for now.
|
||||||
|
// Enable this again with a GODEBUG opt-out.
|
||||||
|
case true:
|
||||||
|
return t, nil
|
||||||
|
case b[len("2006-01-02T")+1] == ':': // hour must be two digits
|
||||||
|
return Time{}, &ParseError{RFC3339, string(b), "15", string(b[len("2006-01-02T"):][:1]), ""}
|
||||||
|
case b[len("2006-01-02T15:04:05")] == ',': // sub-second separator must be a period
|
||||||
|
return Time{}, &ParseError{RFC3339, string(b), ".", ",", ""}
|
||||||
|
case b[len(b)-1] != 'Z':
|
||||||
|
switch {
|
||||||
|
case num2(b[len(b)-len("07:00"):]) >= 24: // timezone hour must be in range
|
||||||
|
return Time{}, &ParseError{RFC3339, string(b), "Z07:00", string(b[len(b)-len("Z07:00"):]), ": timezone hour out of range"}
|
||||||
|
case num2(b[len(b)-len("00"):]) >= 60: // timezone minute must be in range
|
||||||
|
return Time{}, &ParseError{RFC3339, string(b), "Z07:00", string(b[len(b)-len("Z07:00"):]), ": timezone minute out of range"}
|
||||||
|
}
|
||||||
|
default: // unknown error; should not occur
|
||||||
|
return Time{}, &ParseError{RFC3339, string(b), RFC3339, string(b), ""}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return t, nil
|
||||||
|
}
|
||||||
@@ -409,6 +409,50 @@ func (t Time) IsZero() bool {
|
|||||||
return t.sec() == 0 && t.nsec() == 0
|
return t.sec() == 0 && t.nsec() == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// abs returns the time t as an absolute time, adjusted by the zone offset.
|
||||||
|
// It is called when computing a presentation property like Month or Hour.
|
||||||
|
func (t Time) abs() uint64 {
|
||||||
|
l := t.loc
|
||||||
|
// Avoid function calls when possible.
|
||||||
|
if l == nil || l == &localLoc {
|
||||||
|
l = l.get()
|
||||||
|
}
|
||||||
|
sec := t.unixSec()
|
||||||
|
if l != &utcLoc {
|
||||||
|
if l.cacheZone != nil && l.cacheStart <= sec && sec < l.cacheEnd {
|
||||||
|
sec += int64(l.cacheZone.offset)
|
||||||
|
} else {
|
||||||
|
_, offset, _, _, _ := l.lookup(sec)
|
||||||
|
sec += int64(offset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return uint64(sec + (unixToInternal + internalToAbsolute))
|
||||||
|
}
|
||||||
|
|
||||||
|
// locabs is a combination of the Zone and abs methods,
|
||||||
|
// extracting both return values from a single zone lookup.
|
||||||
|
func (t Time) locabs() (name string, offset int, abs uint64) {
|
||||||
|
l := t.loc
|
||||||
|
if l == nil || l == &localLoc {
|
||||||
|
l = l.get()
|
||||||
|
}
|
||||||
|
// Avoid function call if we hit the local time cache.
|
||||||
|
sec := t.unixSec()
|
||||||
|
if l != &utcLoc {
|
||||||
|
if l.cacheZone != nil && l.cacheStart <= sec && sec < l.cacheEnd {
|
||||||
|
name = l.cacheZone.name
|
||||||
|
offset = l.cacheZone.offset
|
||||||
|
} else {
|
||||||
|
name, offset, _, _, _ = l.lookup(sec)
|
||||||
|
}
|
||||||
|
sec += int64(offset)
|
||||||
|
} else {
|
||||||
|
name = "UTC"
|
||||||
|
}
|
||||||
|
abs = uint64(sec + (unixToInternal + internalToAbsolute))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Date returns the Time corresponding to
|
// Date returns the Time corresponding to
|
||||||
//
|
//
|
||||||
// yyyy-mm-dd hh:mm:ss + nsec nanoseconds
|
// yyyy-mm-dd hh:mm:ss + nsec nanoseconds
|
||||||
@@ -481,6 +525,111 @@ func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) T
|
|||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO(xsw):
|
||||||
|
// Year returns the year in which t occurs.
|
||||||
|
func (t Time) Year() int {
|
||||||
|
year, _, _, _ := t.date(false)
|
||||||
|
return year
|
||||||
|
}
|
||||||
|
|
||||||
|
// Month returns the month of the year specified by t.
|
||||||
|
func (t Time) Month() Month {
|
||||||
|
_, month, _, _ := t.date(true)
|
||||||
|
return month
|
||||||
|
}
|
||||||
|
|
||||||
|
// Day returns the day of the month specified by t.
|
||||||
|
func (t Time) Day() int {
|
||||||
|
_, _, day, _ := t.date(true)
|
||||||
|
return day
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Weekday returns the day of the week specified by t.
|
||||||
|
func (t Time) Weekday() Weekday {
|
||||||
|
return absWeekday(t.abs())
|
||||||
|
}
|
||||||
|
|
||||||
|
// absWeekday is like Weekday but operates on an absolute time.
|
||||||
|
func absWeekday(abs uint64) Weekday {
|
||||||
|
// January 1 of the absolute year, like January 1 of 2001, was a Monday.
|
||||||
|
sec := (abs + uint64(Monday)*secondsPerDay) % secondsPerWeek
|
||||||
|
return Weekday(int(sec) / secondsPerDay)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ISOWeek returns the ISO 8601 year and week number in which t occurs.
|
||||||
|
// Week ranges from 1 to 53. Jan 01 to Jan 03 of year n might belong to
|
||||||
|
// week 52 or 53 of year n-1, and Dec 29 to Dec 31 might belong to week 1
|
||||||
|
// of year n+1.
|
||||||
|
func (t Time) ISOWeek() (year, week int) {
|
||||||
|
// According to the rule that the first calendar week of a calendar year is
|
||||||
|
// the week including the first Thursday of that year, and that the last one is
|
||||||
|
// the week immediately preceding the first calendar week of the next calendar year.
|
||||||
|
// See https://www.iso.org/obp/ui#iso:std:iso:8601:-1:ed-1:v1:en:term:3.1.1.23 for details.
|
||||||
|
|
||||||
|
// weeks start with Monday
|
||||||
|
// Monday Tuesday Wednesday Thursday Friday Saturday Sunday
|
||||||
|
// 1 2 3 4 5 6 7
|
||||||
|
// +3 +2 +1 0 -1 -2 -3
|
||||||
|
// the offset to Thursday
|
||||||
|
abs := t.abs()
|
||||||
|
d := Thursday - absWeekday(abs)
|
||||||
|
// handle Sunday
|
||||||
|
if d == 4 {
|
||||||
|
d = -3
|
||||||
|
}
|
||||||
|
// find the Thursday of the calendar week
|
||||||
|
abs += uint64(d) * secondsPerDay
|
||||||
|
year, _, _, yday := absDate(abs, false)
|
||||||
|
return year, yday/7 + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clock returns the hour, minute, and second within the day specified by t.
|
||||||
|
func (t Time) Clock() (hour, min, sec int) {
|
||||||
|
return absClock(t.abs())
|
||||||
|
}
|
||||||
|
|
||||||
|
// absClock is like clock but operates on an absolute time.
|
||||||
|
func absClock(abs uint64) (hour, min, sec int) {
|
||||||
|
sec = int(abs % secondsPerDay)
|
||||||
|
hour = sec / secondsPerHour
|
||||||
|
sec -= hour * secondsPerHour
|
||||||
|
min = sec / secondsPerMinute
|
||||||
|
sec -= min * secondsPerMinute
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hour returns the hour within the day specified by t, in the range [0, 23].
|
||||||
|
func (t Time) Hour() int {
|
||||||
|
return int(t.abs()%secondsPerDay) / secondsPerHour
|
||||||
|
}
|
||||||
|
|
||||||
|
// Minute returns the minute offset within the hour specified by t, in the range [0, 59].
|
||||||
|
func (t Time) Minute() int {
|
||||||
|
return int(t.abs()%secondsPerHour) / secondsPerMinute
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second returns the second offset within the minute specified by t, in the range [0, 59].
|
||||||
|
func (t Time) Second() int {
|
||||||
|
return int(t.abs() % secondsPerMinute)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nanosecond returns the nanosecond offset within the second specified by t,
|
||||||
|
// in the range [0, 999999999].
|
||||||
|
func (t Time) Nanosecond() int {
|
||||||
|
return int(t.nsec())
|
||||||
|
}
|
||||||
|
|
||||||
|
// YearDay returns the day of the year specified by t, in the range [1,365] for non-leap years,
|
||||||
|
// and [1,366] in leap years.
|
||||||
|
func (t Time) YearDay() int {
|
||||||
|
/*
|
||||||
|
_, _, _, yday := t.date(false)
|
||||||
|
return yday + 1
|
||||||
|
*/
|
||||||
|
panic("todo: Time.YearDay")
|
||||||
|
}
|
||||||
|
|
||||||
func unixTime(sec int64, nsec int32) Time {
|
func unixTime(sec int64, nsec int32) Time {
|
||||||
return Time{uint64(nsec), sec + unixToInternal, Local}
|
return Time{uint64(nsec), sec + unixToInternal, Local}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,6 +94,41 @@ func (l *Location) String() string {
|
|||||||
return l.get().name
|
return l.get().name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var unnamedFixedZones []*Location
|
||||||
|
var unnamedFixedZonesOnce sync.Once
|
||||||
|
|
||||||
|
// FixedZone returns a Location that always uses
|
||||||
|
// the given zone name and offset (seconds east of UTC).
|
||||||
|
func FixedZone(name string, offset int) *Location {
|
||||||
|
// Most calls to FixedZone have an unnamed zone with an offset by the hour.
|
||||||
|
// Optimize for that case by returning the same *Location for a given hour.
|
||||||
|
const hoursBeforeUTC = 12
|
||||||
|
const hoursAfterUTC = 14
|
||||||
|
hour := offset / 60 / 60
|
||||||
|
if name == "" && -hoursBeforeUTC <= hour && hour <= +hoursAfterUTC && hour*60*60 == offset {
|
||||||
|
unnamedFixedZonesOnce.Do(func() {
|
||||||
|
unnamedFixedZones = make([]*Location, hoursBeforeUTC+1+hoursAfterUTC)
|
||||||
|
for hr := -hoursBeforeUTC; hr <= +hoursAfterUTC; hr++ {
|
||||||
|
unnamedFixedZones[hr+hoursBeforeUTC] = fixedZone("", hr*60*60)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return unnamedFixedZones[hour+hoursBeforeUTC]
|
||||||
|
}
|
||||||
|
return fixedZone(name, offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
func fixedZone(name string, offset int) *Location {
|
||||||
|
l := &Location{
|
||||||
|
name: name,
|
||||||
|
zone: []zone{{name, offset, false}},
|
||||||
|
tx: []zoneTrans{{alpha, 0, false, false}},
|
||||||
|
cacheStart: alpha,
|
||||||
|
cacheEnd: omega,
|
||||||
|
}
|
||||||
|
l.cacheZone = &l.zone[0]
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
// lookup returns information about the time zone in use at an
|
// lookup returns information about the time zone in use at an
|
||||||
// instant in time expressed as seconds since January 1, 1970 00:00:00 UTC.
|
// instant in time expressed as seconds since January 1, 1970 00:00:00 UTC.
|
||||||
//
|
//
|
||||||
|
|||||||
Reference in New Issue
Block a user