date.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  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. type dateLayoutDesc struct {
  24. layout string
  25. dateOnly bool
  26. }
  27. var (
  28. dateLayoutsNumeric = []dateLayoutDesc{
  29. {layout: "2006-01-02T15:04:05Z0700"},
  30. {layout: "2006-01-02T15:04:05"},
  31. {layout: "2006-01-02", dateOnly: true},
  32. {layout: "2006-01-02 15:04:05"},
  33. {layout: "2006", dateOnly: true},
  34. {layout: "2006-01", dateOnly: true},
  35. {layout: "2006T15:04"},
  36. {layout: "2006-01T15:04"},
  37. {layout: "2006-01-02T15:04"},
  38. {layout: "2006T15:04:05"},
  39. {layout: "2006-01T15:04:05"},
  40. {layout: "2006T15:04Z0700"},
  41. {layout: "2006-01T15:04Z0700"},
  42. {layout: "2006-01-02T15:04Z0700"},
  43. {layout: "2006T15:04:05Z0700"},
  44. {layout: "2006-01T15:04:05Z0700"},
  45. }
  46. dateLayoutsAlpha = []dateLayoutDesc{
  47. {layout: time.RFC1123},
  48. {layout: time.RFC1123Z},
  49. {layout: dateTimeLayout},
  50. {layout: time.UnixDate},
  51. {layout: time.ANSIC},
  52. {layout: time.RubyDate},
  53. {layout: "Mon, _2 Jan 2006 15:04:05 GMT-0700 (MST)"},
  54. {layout: "Mon, _2 Jan 2006 15:04:05 -0700 (MST)"},
  55. {layout: "Jan _2, 2006", dateOnly: true},
  56. }
  57. )
  58. func dateParse(date string) (time.Time, bool) {
  59. var t time.Time
  60. var err error
  61. var layouts []dateLayoutDesc
  62. if len(date) > 0 {
  63. first := date[0]
  64. if first <= '9' && (first >= '0' || first == '-' || first == '+') {
  65. layouts = dateLayoutsNumeric
  66. } else {
  67. layouts = dateLayoutsAlpha
  68. }
  69. } else {
  70. return time.Time{}, false
  71. }
  72. for _, desc := range layouts {
  73. var defLoc *time.Location
  74. if desc.dateOnly {
  75. defLoc = time.UTC
  76. } else {
  77. defLoc = time.Local
  78. }
  79. t, err = parseDate(desc.layout, date, defLoc)
  80. if err == nil {
  81. break
  82. }
  83. }
  84. if err != nil {
  85. return time.Time{}, false
  86. }
  87. unix := timeToMsec(t)
  88. return t, unix >= -maxTime && unix <= maxTime
  89. }
  90. func (r *Runtime) newDateObject(t time.Time, isSet bool, proto *Object) *Object {
  91. v := &Object{runtime: r}
  92. d := &dateObject{}
  93. v.self = d
  94. d.val = v
  95. d.class = classDate
  96. d.prototype = proto
  97. d.extensible = true
  98. d.init()
  99. if isSet {
  100. d.msec = timeToMsec(t)
  101. } else {
  102. d.msec = timeUnset
  103. }
  104. return v
  105. }
  106. func dateFormat(t time.Time) string {
  107. return t.Local().Format(dateTimeLayout)
  108. }
  109. func timeFromMsec(msec int64) time.Time {
  110. sec := msec / 1000
  111. nsec := (msec % 1000) * 1e6
  112. return time.Unix(sec, nsec)
  113. }
  114. func timeToMsec(t time.Time) int64 {
  115. return t.Unix()*1000 + int64(t.Nanosecond())/1e6
  116. }
  117. func (d *dateObject) toPrimitive() Value {
  118. return d.toPrimitiveString()
  119. }
  120. func (d *dateObject) exportType() reflect.Type {
  121. return typeTime
  122. }
  123. func (d *dateObject) export(*objectExportCtx) interface{} {
  124. if d.isSet() {
  125. return d.time()
  126. }
  127. return nil
  128. }
  129. func (d *dateObject) setTimeMs(ms int64) Value {
  130. if ms >= 0 && ms <= maxTime || ms < 0 && ms >= -maxTime {
  131. d.msec = ms
  132. return intToValue(ms)
  133. }
  134. d.unset()
  135. return _NaN
  136. }
  137. func (d *dateObject) isSet() bool {
  138. return d.msec != timeUnset
  139. }
  140. func (d *dateObject) unset() {
  141. d.msec = timeUnset
  142. }
  143. func (d *dateObject) time() time.Time {
  144. return timeFromMsec(d.msec)
  145. }
  146. func (d *dateObject) timeUTC() time.Time {
  147. return timeFromMsec(d.msec).In(time.UTC)
  148. }