125 lines
2.4 KiB
Go
125 lines
2.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
|
|
}
|
|
|
|
func dateParse(date string) (t time.Time, ok bool) {
|
|
d, ok := parseDateISOString(date)
|
|
if !ok {
|
|
d, ok = parseDateOtherString(date)
|
|
}
|
|
if !ok {
|
|
return
|
|
}
|
|
if d.month > 12 ||
|
|
d.day > 31 ||
|
|
d.hour > 24 ||
|
|
d.min > 59 ||
|
|
d.sec > 59 ||
|
|
// special case 24:00:00.000
|
|
(d.hour == 24 && (d.min != 0 || d.sec != 0 || d.msec != 0)) {
|
|
ok = false
|
|
return
|
|
}
|
|
var loc *time.Location
|
|
if d.isLocal {
|
|
loc = time.Local
|
|
} else {
|
|
loc = time.FixedZone("", d.timeZoneOffset*60)
|
|
}
|
|
t = time.Date(d.year, time.Month(d.month), d.day, d.hour, d.min, d.sec, d.msec*1e6, loc)
|
|
unixMilli := t.UnixMilli()
|
|
ok = unixMilli >= -maxTime && unixMilli <= maxTime
|
|
return
|
|
}
|
|
|
|
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)
|
|
}
|