ai_old/goja/date.go
2024-09-20 16:50:35 +08:00

171 lines
3.4 KiB
Go

package goja
import (
"math"
"reflect"
"time"
)
const (
dateTimeLayout = "Mon Jan 02 2006 15:04:05 GMT-0700 (MST)"
utcDateTimeLayout = "Mon, 02 Jan 2006 15:04:05 GMT"
isoDateTimeLayout = "2006-01-02T15:04:05.000Z"
dateLayout = "Mon Jan 02 2006"
timeLayout = "15:04:05 GMT-0700 (MST)"
datetimeLayout_en_GB = "01/02/2006, 15:04:05"
dateLayout_en_GB = "01/02/2006"
timeLayout_en_GB = "15:04:05"
maxTime = 8.64e15
timeUnset = math.MinInt64
)
type dateObject struct {
baseObject
msec int64
}
type dateLayoutDesc struct {
layout string
dateOnly bool
}
var (
dateLayoutsNumeric = []dateLayoutDesc{
{layout: "2006-01-02T15:04:05Z0700"},
{layout: "2006-01-02T15:04:05"},
{layout: "2006-01-02", dateOnly: true},
{layout: "2006-01-02 15:04:05"},
{layout: "2006", dateOnly: true},
{layout: "2006-01", dateOnly: true},
{layout: "2006T15:04"},
{layout: "2006-01T15:04"},
{layout: "2006-01-02T15:04"},
{layout: "2006T15:04:05"},
{layout: "2006-01T15:04:05"},
{layout: "2006T15:04Z0700"},
{layout: "2006-01T15:04Z0700"},
{layout: "2006-01-02T15:04Z0700"},
{layout: "2006T15:04:05Z0700"},
{layout: "2006-01T15:04:05Z0700"},
}
dateLayoutsAlpha = []dateLayoutDesc{
{layout: time.RFC1123},
{layout: time.RFC1123Z},
{layout: dateTimeLayout},
{layout: time.UnixDate},
{layout: time.ANSIC},
{layout: time.RubyDate},
{layout: "Mon, _2 Jan 2006 15:04:05 GMT-0700 (MST)"},
{layout: "Mon, _2 Jan 2006 15:04:05 -0700 (MST)"},
{layout: "Jan _2, 2006", dateOnly: true},
}
)
func dateParse(date string) (time.Time, bool) {
var t time.Time
var err error
var layouts []dateLayoutDesc
if len(date) > 0 {
first := date[0]
if first <= '9' && (first >= '0' || first == '-' || first == '+') {
layouts = dateLayoutsNumeric
} else {
layouts = dateLayoutsAlpha
}
} else {
return time.Time{}, false
}
for _, desc := range layouts {
var defLoc *time.Location
if desc.dateOnly {
defLoc = time.UTC
} else {
defLoc = time.Local
}
t, err = parseDate(desc.layout, date, defLoc)
if err == nil {
break
}
}
if err != nil {
return time.Time{}, false
}
unix := timeToMsec(t)
return t, unix >= -maxTime && unix <= maxTime
}
func (r *Runtime) newDateObject(t time.Time, isSet bool, proto *Object) *Object {
v := &Object{runtime: r}
d := &dateObject{}
v.self = d
d.val = v
d.class = classDate
d.prototype = proto
d.extensible = true
d.init()
if isSet {
d.msec = timeToMsec(t)
} else {
d.msec = timeUnset
}
return v
}
func dateFormat(t time.Time) string {
return t.Local().Format(dateTimeLayout)
}
func timeFromMsec(msec int64) time.Time {
sec := msec / 1000
nsec := (msec % 1000) * 1e6
return time.Unix(sec, nsec)
}
func timeToMsec(t time.Time) int64 {
return t.Unix()*1000 + int64(t.Nanosecond())/1e6
}
func (d *dateObject) exportType() reflect.Type {
return typeTime
}
func (d *dateObject) export(*objectExportCtx) interface{} {
if d.isSet() {
return d.time()
}
return nil
}
func (d *dateObject) setTimeMs(ms int64) Value {
if ms >= 0 && ms <= maxTime || ms < 0 && ms >= -maxTime {
d.msec = ms
return intToValue(ms)
}
d.unset()
return _NaN
}
func (d *dateObject) isSet() bool {
return d.msec != timeUnset
}
func (d *dateObject) unset() {
d.msec = timeUnset
}
func (d *dateObject) time() time.Time {
return timeFromMsec(d.msec)
}
func (d *dateObject) timeUTC() time.Time {
return timeFromMsec(d.msec).In(time.UTC)
}