date.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. package goja
  2. import (
  3. "math"
  4. "reflect"
  5. "time"
  6. )
  7. const (
  8. dateTimeLayout = "Mon Jan 02 2006 15:04:05 GMT-0700 (MST)"
  9. utcDateTimeLayout = "Mon, 02 Jan 2006 15:04:05 GMT"
  10. isoDateTimeLayout = "2006-01-02T15:04:05.000Z"
  11. dateLayout = "Mon Jan 02 2006"
  12. timeLayout = "15:04:05 GMT-0700 (MST)"
  13. datetimeLayout_en_GB = "01/02/2006, 15:04:05"
  14. dateLayout_en_GB = "01/02/2006"
  15. timeLayout_en_GB = "15:04:05"
  16. maxTime = 8.64e15
  17. timeUnset = math.MinInt64
  18. )
  19. type dateObject struct {
  20. baseObject
  21. msec int64
  22. }
  23. func dateParse(date string) (t time.Time, ok bool) {
  24. d, ok := parseDateISOString(date)
  25. if !ok {
  26. d, ok = parseDateOtherString(date)
  27. }
  28. if !ok {
  29. return
  30. }
  31. if d.month > 12 ||
  32. d.day > 31 ||
  33. d.hour > 24 ||
  34. d.min > 59 ||
  35. d.sec > 59 ||
  36. // special case 24:00:00.000
  37. (d.hour == 24 && (d.min != 0 || d.sec != 0 || d.msec != 0)) {
  38. ok = false
  39. return
  40. }
  41. var loc *time.Location
  42. if d.isLocal {
  43. loc = time.Local
  44. } else {
  45. loc = time.FixedZone("", d.timeZoneOffset*60)
  46. }
  47. t = time.Date(d.year, time.Month(d.month), d.day, d.hour, d.min, d.sec, d.msec*1e6, loc)
  48. unixMilli := t.UnixMilli()
  49. ok = unixMilli >= -maxTime && unixMilli <= maxTime
  50. return
  51. }
  52. func (r *Runtime) newDateObject(t time.Time, isSet bool, proto *Object) *Object {
  53. v := &Object{runtime: r}
  54. d := &dateObject{}
  55. v.self = d
  56. d.val = v
  57. d.class = classDate
  58. d.prototype = proto
  59. d.extensible = true
  60. d.init()
  61. if isSet {
  62. d.msec = timeToMsec(t)
  63. } else {
  64. d.msec = timeUnset
  65. }
  66. return v
  67. }
  68. func dateFormat(t time.Time) string {
  69. return t.Local().Format(dateTimeLayout)
  70. }
  71. func timeFromMsec(msec int64) time.Time {
  72. sec := msec / 1000
  73. nsec := (msec % 1000) * 1e6
  74. return time.Unix(sec, nsec)
  75. }
  76. func timeToMsec(t time.Time) int64 {
  77. return t.Unix()*1000 + int64(t.Nanosecond())/1e6
  78. }
  79. func (d *dateObject) exportType() reflect.Type {
  80. return typeTime
  81. }
  82. func (d *dateObject) export(*objectExportCtx) interface{} {
  83. if d.isSet() {
  84. return d.time()
  85. }
  86. return nil
  87. }
  88. func (d *dateObject) setTimeMs(ms int64) Value {
  89. if ms >= 0 && ms <= maxTime || ms < 0 && ms >= -maxTime {
  90. d.msec = ms
  91. return intToValue(ms)
  92. }
  93. d.unset()
  94. return _NaN
  95. }
  96. func (d *dateObject) isSet() bool {
  97. return d.msec != timeUnset
  98. }
  99. func (d *dateObject) unset() {
  100. d.msec = timeUnset
  101. }
  102. func (d *dateObject) time() time.Time {
  103. return timeFromMsec(d.msec)
  104. }
  105. func (d *dateObject) timeUTC() time.Time {
  106. return timeFromMsec(d.msec).In(time.UTC)
  107. }