builtin_date.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  1. package otto
  2. import (
  3. "math"
  4. Time "time"
  5. )
  6. // Date
  7. const (
  8. // TODO Be like V8?
  9. // builtinDate_goDateTimeLayout = "Mon Jan 2 2006 15:04:05 GMT-0700 (MST)"
  10. builtinDate_goDateTimeLayout = Time.RFC1123 // "Mon, 02 Jan 2006 15:04:05 MST"
  11. builtinDate_goDateLayout = "Mon, 02 Jan 2006"
  12. builtinDate_goTimeLayout = "15:04:05 MST"
  13. )
  14. func builtinDate(call FunctionCall) Value {
  15. date := &_dateObject{}
  16. date.Set(newDateTime([]Value{}, Time.Local))
  17. return toValue_string(date.Time().Format(builtinDate_goDateTimeLayout))
  18. }
  19. func builtinNewDate(self *_object, argumentList []Value) Value {
  20. return toValue_object(self.runtime.newDate(newDateTime(argumentList, Time.Local)))
  21. }
  22. func builtinDate_toString(call FunctionCall) Value {
  23. date := dateObjectOf(call.runtime, call.thisObject())
  24. if date.isNaN {
  25. return toValue_string("Invalid Date")
  26. }
  27. return toValue_string(date.Time().Local().Format(builtinDate_goDateTimeLayout))
  28. }
  29. func builtinDate_toDateString(call FunctionCall) Value {
  30. date := dateObjectOf(call.runtime, call.thisObject())
  31. if date.isNaN {
  32. return toValue_string("Invalid Date")
  33. }
  34. return toValue_string(date.Time().Local().Format(builtinDate_goDateLayout))
  35. }
  36. func builtinDate_toTimeString(call FunctionCall) Value {
  37. date := dateObjectOf(call.runtime, call.thisObject())
  38. if date.isNaN {
  39. return toValue_string("Invalid Date")
  40. }
  41. return toValue_string(date.Time().Local().Format(builtinDate_goTimeLayout))
  42. }
  43. func builtinDate_toUTCString(call FunctionCall) Value {
  44. date := dateObjectOf(call.runtime, call.thisObject())
  45. if date.isNaN {
  46. return toValue_string("Invalid Date")
  47. }
  48. return toValue_string(date.Time().Format(builtinDate_goDateTimeLayout))
  49. }
  50. func builtinDate_toISOString(call FunctionCall) Value {
  51. date := dateObjectOf(call.runtime, call.thisObject())
  52. if date.isNaN {
  53. return toValue_string("Invalid Date")
  54. }
  55. return toValue_string(date.Time().Format("2006-01-02T15:04:05.000Z"))
  56. }
  57. func builtinDate_toJSON(call FunctionCall) Value {
  58. object := call.thisObject()
  59. value := object.DefaultValue(defaultValueHintNumber) // FIXME object.primitiveNumberValue
  60. { // FIXME value.isFinite
  61. value := value.float64()
  62. if math.IsNaN(value) || math.IsInf(value, 0) {
  63. return nullValue
  64. }
  65. }
  66. toISOString := object.get("toISOString")
  67. if !toISOString.isCallable() {
  68. // FIXME
  69. panic(call.runtime.panicTypeError())
  70. }
  71. return toISOString.call(call.runtime, toValue_object(object), []Value{})
  72. }
  73. func builtinDate_toGMTString(call FunctionCall) Value {
  74. date := dateObjectOf(call.runtime, call.thisObject())
  75. if date.isNaN {
  76. return toValue_string("Invalid Date")
  77. }
  78. return toValue_string(date.Time().Format("Mon, 02 Jan 2006 15:04:05 GMT"))
  79. }
  80. func builtinDate_getTime(call FunctionCall) Value {
  81. date := dateObjectOf(call.runtime, call.thisObject())
  82. if date.isNaN {
  83. return NaNValue()
  84. }
  85. // We do this (convert away from a float) so the user
  86. // does not get something back in exponential notation
  87. return toValue_int64(int64(date.Epoch()))
  88. }
  89. func builtinDate_setTime(call FunctionCall) Value {
  90. object := call.thisObject()
  91. date := dateObjectOf(call.runtime, call.thisObject())
  92. date.Set(call.Argument(0).float64())
  93. object.value = date
  94. return date.Value()
  95. }
  96. func _builtinDate_beforeSet(call FunctionCall, argumentLimit int, timeLocal bool) (*_object, *_dateObject, *_ecmaTime, []int) {
  97. object := call.thisObject()
  98. date := dateObjectOf(call.runtime, call.thisObject())
  99. if date.isNaN {
  100. return nil, nil, nil, nil
  101. }
  102. if argumentLimit > len(call.ArgumentList) {
  103. argumentLimit = len(call.ArgumentList)
  104. }
  105. if argumentLimit == 0 {
  106. object.value = invalidDateObject
  107. return nil, nil, nil, nil
  108. }
  109. valueList := make([]int, argumentLimit)
  110. for index := 0; index < argumentLimit; index++ {
  111. value := call.ArgumentList[index]
  112. nm := value.number()
  113. switch nm.kind {
  114. case numberInteger, numberFloat:
  115. default:
  116. object.value = invalidDateObject
  117. return nil, nil, nil, nil
  118. }
  119. valueList[index] = int(nm.int64)
  120. }
  121. baseTime := date.Time()
  122. if timeLocal {
  123. baseTime = baseTime.Local()
  124. }
  125. ecmaTime := ecmaTime(baseTime)
  126. return object, &date, &ecmaTime, valueList
  127. }
  128. func builtinDate_parse(call FunctionCall) Value {
  129. date := call.Argument(0).string()
  130. return toValue_float64(dateParse(date))
  131. }
  132. func builtinDate_UTC(call FunctionCall) Value {
  133. return toValue_float64(newDateTime(call.ArgumentList, Time.UTC))
  134. }
  135. func builtinDate_now(call FunctionCall) Value {
  136. call.ArgumentList = []Value(nil)
  137. return builtinDate_UTC(call)
  138. }
  139. // This is a placeholder
  140. func builtinDate_toLocaleString(call FunctionCall) Value {
  141. date := dateObjectOf(call.runtime, call.thisObject())
  142. if date.isNaN {
  143. return toValue_string("Invalid Date")
  144. }
  145. return toValue_string(date.Time().Local().Format("2006-01-02 15:04:05"))
  146. }
  147. // This is a placeholder
  148. func builtinDate_toLocaleDateString(call FunctionCall) Value {
  149. date := dateObjectOf(call.runtime, call.thisObject())
  150. if date.isNaN {
  151. return toValue_string("Invalid Date")
  152. }
  153. return toValue_string(date.Time().Local().Format("2006-01-02"))
  154. }
  155. // This is a placeholder
  156. func builtinDate_toLocaleTimeString(call FunctionCall) Value {
  157. date := dateObjectOf(call.runtime, call.thisObject())
  158. if date.isNaN {
  159. return toValue_string("Invalid Date")
  160. }
  161. return toValue_string(date.Time().Local().Format("15:04:05"))
  162. }
  163. func builtinDate_valueOf(call FunctionCall) Value {
  164. date := dateObjectOf(call.runtime, call.thisObject())
  165. if date.isNaN {
  166. return NaNValue()
  167. }
  168. return date.Value()
  169. }
  170. func builtinDate_getYear(call FunctionCall) Value {
  171. // Will throw a TypeError is ThisObject is nil or
  172. // does not have Class of "Date"
  173. date := dateObjectOf(call.runtime, call.thisObject())
  174. if date.isNaN {
  175. return NaNValue()
  176. }
  177. return toValue_int(date.Time().Local().Year() - 1900)
  178. }
  179. func builtinDate_getFullYear(call FunctionCall) Value {
  180. // Will throw a TypeError is ThisObject is nil or
  181. // does not have Class of "Date"
  182. date := dateObjectOf(call.runtime, call.thisObject())
  183. if date.isNaN {
  184. return NaNValue()
  185. }
  186. return toValue_int(date.Time().Local().Year())
  187. }
  188. func builtinDate_getUTCFullYear(call FunctionCall) Value {
  189. date := dateObjectOf(call.runtime, call.thisObject())
  190. if date.isNaN {
  191. return NaNValue()
  192. }
  193. return toValue_int(date.Time().Year())
  194. }
  195. func builtinDate_getMonth(call FunctionCall) Value {
  196. date := dateObjectOf(call.runtime, call.thisObject())
  197. if date.isNaN {
  198. return NaNValue()
  199. }
  200. return toValue_int(dateFromGoMonth(date.Time().Local().Month()))
  201. }
  202. func builtinDate_getUTCMonth(call FunctionCall) Value {
  203. date := dateObjectOf(call.runtime, call.thisObject())
  204. if date.isNaN {
  205. return NaNValue()
  206. }
  207. return toValue_int(dateFromGoMonth(date.Time().Month()))
  208. }
  209. func builtinDate_getDate(call FunctionCall) Value {
  210. date := dateObjectOf(call.runtime, call.thisObject())
  211. if date.isNaN {
  212. return NaNValue()
  213. }
  214. return toValue_int(date.Time().Local().Day())
  215. }
  216. func builtinDate_getUTCDate(call FunctionCall) Value {
  217. date := dateObjectOf(call.runtime, call.thisObject())
  218. if date.isNaN {
  219. return NaNValue()
  220. }
  221. return toValue_int(date.Time().Day())
  222. }
  223. func builtinDate_getDay(call FunctionCall) Value {
  224. // Actually day of the week
  225. date := dateObjectOf(call.runtime, call.thisObject())
  226. if date.isNaN {
  227. return NaNValue()
  228. }
  229. return toValue_int(dateFromGoDay(date.Time().Local().Weekday()))
  230. }
  231. func builtinDate_getUTCDay(call FunctionCall) Value {
  232. date := dateObjectOf(call.runtime, call.thisObject())
  233. if date.isNaN {
  234. return NaNValue()
  235. }
  236. return toValue_int(dateFromGoDay(date.Time().Weekday()))
  237. }
  238. func builtinDate_getHours(call FunctionCall) Value {
  239. date := dateObjectOf(call.runtime, call.thisObject())
  240. if date.isNaN {
  241. return NaNValue()
  242. }
  243. return toValue_int(date.Time().Local().Hour())
  244. }
  245. func builtinDate_getUTCHours(call FunctionCall) Value {
  246. date := dateObjectOf(call.runtime, call.thisObject())
  247. if date.isNaN {
  248. return NaNValue()
  249. }
  250. return toValue_int(date.Time().Hour())
  251. }
  252. func builtinDate_getMinutes(call FunctionCall) Value {
  253. date := dateObjectOf(call.runtime, call.thisObject())
  254. if date.isNaN {
  255. return NaNValue()
  256. }
  257. return toValue_int(date.Time().Local().Minute())
  258. }
  259. func builtinDate_getUTCMinutes(call FunctionCall) Value {
  260. date := dateObjectOf(call.runtime, call.thisObject())
  261. if date.isNaN {
  262. return NaNValue()
  263. }
  264. return toValue_int(date.Time().Minute())
  265. }
  266. func builtinDate_getSeconds(call FunctionCall) Value {
  267. date := dateObjectOf(call.runtime, call.thisObject())
  268. if date.isNaN {
  269. return NaNValue()
  270. }
  271. return toValue_int(date.Time().Local().Second())
  272. }
  273. func builtinDate_getUTCSeconds(call FunctionCall) Value {
  274. date := dateObjectOf(call.runtime, call.thisObject())
  275. if date.isNaN {
  276. return NaNValue()
  277. }
  278. return toValue_int(date.Time().Second())
  279. }
  280. func builtinDate_getMilliseconds(call FunctionCall) Value {
  281. date := dateObjectOf(call.runtime, call.thisObject())
  282. if date.isNaN {
  283. return NaNValue()
  284. }
  285. return toValue_int(date.Time().Local().Nanosecond() / (100 * 100 * 100))
  286. }
  287. func builtinDate_getUTCMilliseconds(call FunctionCall) Value {
  288. date := dateObjectOf(call.runtime, call.thisObject())
  289. if date.isNaN {
  290. return NaNValue()
  291. }
  292. return toValue_int(date.Time().Nanosecond() / (100 * 100 * 100))
  293. }
  294. func builtinDate_getTimezoneOffset(call FunctionCall) Value {
  295. date := dateObjectOf(call.runtime, call.thisObject())
  296. if date.isNaN {
  297. return NaNValue()
  298. }
  299. timeLocal := date.Time().Local()
  300. // Is this kosher?
  301. timeLocalAsUTC := Time.Date(
  302. timeLocal.Year(),
  303. timeLocal.Month(),
  304. timeLocal.Day(),
  305. timeLocal.Hour(),
  306. timeLocal.Minute(),
  307. timeLocal.Second(),
  308. timeLocal.Nanosecond(),
  309. Time.UTC,
  310. )
  311. return toValue_float64(date.Time().Sub(timeLocalAsUTC).Seconds() / 60)
  312. }
  313. func builtinDate_setMilliseconds(call FunctionCall) Value {
  314. object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, true)
  315. if ecmaTime == nil {
  316. return NaNValue()
  317. }
  318. ecmaTime.millisecond = value[0]
  319. date.SetTime(ecmaTime.goTime())
  320. object.value = *date
  321. return date.Value()
  322. }
  323. func builtinDate_setUTCMilliseconds(call FunctionCall) Value {
  324. object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, false)
  325. if ecmaTime == nil {
  326. return NaNValue()
  327. }
  328. ecmaTime.millisecond = value[0]
  329. date.SetTime(ecmaTime.goTime())
  330. object.value = *date
  331. return date.Value()
  332. }
  333. func builtinDate_setSeconds(call FunctionCall) Value {
  334. object, date, ecmaTime, value := _builtinDate_beforeSet(call, 2, true)
  335. if ecmaTime == nil {
  336. return NaNValue()
  337. }
  338. if len(value) > 1 {
  339. ecmaTime.millisecond = value[1]
  340. }
  341. ecmaTime.second = value[0]
  342. date.SetTime(ecmaTime.goTime())
  343. object.value = *date
  344. return date.Value()
  345. }
  346. func builtinDate_setUTCSeconds(call FunctionCall) Value {
  347. object, date, ecmaTime, value := _builtinDate_beforeSet(call, 2, false)
  348. if ecmaTime == nil {
  349. return NaNValue()
  350. }
  351. if len(value) > 1 {
  352. ecmaTime.millisecond = value[1]
  353. }
  354. ecmaTime.second = value[0]
  355. date.SetTime(ecmaTime.goTime())
  356. object.value = *date
  357. return date.Value()
  358. }
  359. func builtinDate_setMinutes(call FunctionCall) Value {
  360. object, date, ecmaTime, value := _builtinDate_beforeSet(call, 3, true)
  361. if ecmaTime == nil {
  362. return NaNValue()
  363. }
  364. if len(value) > 2 {
  365. ecmaTime.millisecond = value[2]
  366. ecmaTime.second = value[1]
  367. } else if len(value) > 1 {
  368. ecmaTime.second = value[1]
  369. }
  370. ecmaTime.minute = value[0]
  371. date.SetTime(ecmaTime.goTime())
  372. object.value = *date
  373. return date.Value()
  374. }
  375. func builtinDate_setUTCMinutes(call FunctionCall) Value {
  376. object, date, ecmaTime, value := _builtinDate_beforeSet(call, 3, false)
  377. if ecmaTime == nil {
  378. return NaNValue()
  379. }
  380. if len(value) > 2 {
  381. ecmaTime.millisecond = value[2]
  382. ecmaTime.second = value[1]
  383. } else if len(value) > 1 {
  384. ecmaTime.second = value[1]
  385. }
  386. ecmaTime.minute = value[0]
  387. date.SetTime(ecmaTime.goTime())
  388. object.value = *date
  389. return date.Value()
  390. }
  391. func builtinDate_setHours(call FunctionCall) Value {
  392. object, date, ecmaTime, value := _builtinDate_beforeSet(call, 4, true)
  393. if ecmaTime == nil {
  394. return NaNValue()
  395. }
  396. if len(value) > 3 {
  397. ecmaTime.millisecond = value[3]
  398. ecmaTime.second = value[2]
  399. ecmaTime.minute = value[1]
  400. } else if len(value) > 2 {
  401. ecmaTime.second = value[2]
  402. ecmaTime.minute = value[1]
  403. } else if len(value) > 1 {
  404. ecmaTime.minute = value[1]
  405. }
  406. ecmaTime.hour = value[0]
  407. date.SetTime(ecmaTime.goTime())
  408. object.value = *date
  409. return date.Value()
  410. }
  411. func builtinDate_setUTCHours(call FunctionCall) Value {
  412. object, date, ecmaTime, value := _builtinDate_beforeSet(call, 4, false)
  413. if ecmaTime == nil {
  414. return NaNValue()
  415. }
  416. if len(value) > 3 {
  417. ecmaTime.millisecond = value[3]
  418. ecmaTime.second = value[2]
  419. ecmaTime.minute = value[1]
  420. } else if len(value) > 2 {
  421. ecmaTime.second = value[2]
  422. ecmaTime.minute = value[1]
  423. } else if len(value) > 1 {
  424. ecmaTime.minute = value[1]
  425. }
  426. ecmaTime.hour = value[0]
  427. date.SetTime(ecmaTime.goTime())
  428. object.value = *date
  429. return date.Value()
  430. }
  431. func builtinDate_setDate(call FunctionCall) Value {
  432. object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, true)
  433. if ecmaTime == nil {
  434. return NaNValue()
  435. }
  436. ecmaTime.day = value[0]
  437. date.SetTime(ecmaTime.goTime())
  438. object.value = *date
  439. return date.Value()
  440. }
  441. func builtinDate_setUTCDate(call FunctionCall) Value {
  442. object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, false)
  443. if ecmaTime == nil {
  444. return NaNValue()
  445. }
  446. ecmaTime.day = value[0]
  447. date.SetTime(ecmaTime.goTime())
  448. object.value = *date
  449. return date.Value()
  450. }
  451. func builtinDate_setMonth(call FunctionCall) Value {
  452. object, date, ecmaTime, value := _builtinDate_beforeSet(call, 2, true)
  453. if ecmaTime == nil {
  454. return NaNValue()
  455. }
  456. if len(value) > 1 {
  457. ecmaTime.day = value[1]
  458. }
  459. ecmaTime.month = value[0]
  460. date.SetTime(ecmaTime.goTime())
  461. object.value = *date
  462. return date.Value()
  463. }
  464. func builtinDate_setUTCMonth(call FunctionCall) Value {
  465. object, date, ecmaTime, value := _builtinDate_beforeSet(call, 2, false)
  466. if ecmaTime == nil {
  467. return NaNValue()
  468. }
  469. if len(value) > 1 {
  470. ecmaTime.day = value[1]
  471. }
  472. ecmaTime.month = value[0]
  473. date.SetTime(ecmaTime.goTime())
  474. object.value = *date
  475. return date.Value()
  476. }
  477. func builtinDate_setYear(call FunctionCall) Value {
  478. object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, true)
  479. if ecmaTime == nil {
  480. return NaNValue()
  481. }
  482. year := value[0]
  483. if 0 <= year && year <= 99 {
  484. year += 1900
  485. }
  486. ecmaTime.year = year
  487. date.SetTime(ecmaTime.goTime())
  488. object.value = *date
  489. return date.Value()
  490. }
  491. func builtinDate_setFullYear(call FunctionCall) Value {
  492. object, date, ecmaTime, value := _builtinDate_beforeSet(call, 3, true)
  493. if ecmaTime == nil {
  494. return NaNValue()
  495. }
  496. if len(value) > 2 {
  497. ecmaTime.day = value[2]
  498. ecmaTime.month = value[1]
  499. } else if len(value) > 1 {
  500. ecmaTime.month = value[1]
  501. }
  502. ecmaTime.year = value[0]
  503. date.SetTime(ecmaTime.goTime())
  504. object.value = *date
  505. return date.Value()
  506. }
  507. func builtinDate_setUTCFullYear(call FunctionCall) Value {
  508. object, date, ecmaTime, value := _builtinDate_beforeSet(call, 3, false)
  509. if ecmaTime == nil {
  510. return NaNValue()
  511. }
  512. if len(value) > 2 {
  513. ecmaTime.day = value[2]
  514. ecmaTime.month = value[1]
  515. } else if len(value) > 1 {
  516. ecmaTime.month = value[1]
  517. }
  518. ecmaTime.year = value[0]
  519. date.SetTime(ecmaTime.goTime())
  520. object.value = *date
  521. return date.Value()
  522. }
  523. // toUTCString
  524. // toISOString
  525. // toJSONString
  526. // toJSON