1package otto
2
3import (
4	"math"
5	"testing"
6	"time"
7)
8
9func mockTimeLocal(location *time.Location) func() {
10	local := time.Local
11	time.Local = location
12	return func() {
13		time.Local = local
14	}
15}
16
17// Passing or failing should not be dependent on what time zone we're in
18func mockUTC() func() {
19	return mockTimeLocal(time.UTC)
20}
21
22func TestDate(t *testing.T) {
23	tt(t, func() {
24		test, _ := test()
25
26		defer mockUTC()()
27
28		time0 := time.Unix(1348616313, 47*1000*1000).Local()
29
30		test(`Date`, "function Date() { [native code] }")
31		test(`new Date(0).toUTCString()`, "Thu, 01 Jan 1970 00:00:00 UTC")
32		test(`new Date(0).toGMTString()`, "Thu, 01 Jan 1970 00:00:00 GMT")
33		if false {
34			// TODO toLocale{Date,Time}String
35			test(`new Date(0).toLocaleString()`, "")
36			test(`new Date(0).toLocaleDateString()`, "")
37			test(`new Date(0).toLocaleTimeString()`, "")
38		}
39		test(`new Date(1348616313).getTime()`, 1348616313)
40		test(`new Date(1348616313).toUTCString()`, "Fri, 16 Jan 1970 14:36:56 UTC")
41		test(`abc = new Date(1348616313047); abc.toUTCString()`, "Tue, 25 Sep 2012 23:38:33 UTC")
42		test(`abc.getYear()`, time0.Year()-1900)
43		test(`abc.getFullYear()`, time0.Year())
44		test(`abc.getUTCFullYear()`, 2012)
45		test(`abc.getMonth()`, int(time0.Month())-1) // Remember, the JavaScript month is 0-based
46		test(`abc.getUTCMonth()`, 8)
47		test(`abc.getDate()`, time0.Day())
48		test(`abc.getUTCDate()`, 25)
49		test(`abc.getDay()`, int(time0.Weekday()))
50		test(`abc.getUTCDay()`, 2)
51		test(`abc.getHours()`, time0.Hour())
52		test(`abc.getUTCHours()`, 23)
53		test(`abc.getMinutes()`, time0.Minute())
54		test(`abc.getUTCMinutes()`, 38)
55		test(`abc.getSeconds()`, time0.Second())
56		test(`abc.getUTCSeconds()`, 33)
57		test(`abc.getMilliseconds()`, time0.Nanosecond()/(1000*1000)) // In honor of the 47%
58		test(`abc.getUTCMilliseconds()`, 47)
59		_, offset := time0.Zone()
60		test(`abc.getTimezoneOffset()`, offset/-60)
61
62		test(`new Date("Xyzzy").getTime()`, math.NaN())
63
64		test(`abc.setFullYear(2011); abc.toUTCString()`, "Sun, 25 Sep 2011 23:38:33 UTC")
65		test(`new Date(12564504e5).toUTCString()`, "Sun, 25 Oct 2009 06:00:00 UTC")
66		test(`new Date(2009, 9, 25).toUTCString()`, "Sun, 25 Oct 2009 00:00:00 UTC")
67		test(`+(new Date(2009, 9, 25))`, 1256428800000)
68
69		format := "Mon, 2 Jan 2006 15:04:05 MST"
70
71		time1 := time.Unix(1256450400, 0)
72		time0 = time.Date(time1.Year(), time1.Month(), time1.Day(), time1.Hour(), time1.Minute(), time1.Second(), time1.Nanosecond(), time1.Location()).UTC()
73
74		time0 = time.Date(time1.Year(), time1.Month(), time1.Day(), time1.Hour(), time1.Minute(), time1.Second(), 2001*1000*1000, time1.Location()).UTC()
75		test(`abc = new Date(12564504e5); abc.setMilliseconds(2001); abc.toUTCString()`, time0.Format(format))
76
77		time0 = time.Date(time1.Year(), time1.Month(), time1.Day(), time1.Hour(), time1.Minute(), 61, time1.Nanosecond(), time1.Location()).UTC()
78		test(`abc = new Date(12564504e5); abc.setSeconds("61"); abc.toUTCString()`, time0.Format(format))
79
80		time0 = time.Date(time1.Year(), time1.Month(), time1.Day(), time1.Hour(), 61, time1.Second(), time1.Nanosecond(), time1.Location()).UTC()
81		test(`abc = new Date(12564504e5); abc.setMinutes("61"); abc.toUTCString()`, time0.Format(format))
82
83		time0 = time.Date(time1.Year(), time1.Month(), time1.Day(), 5, time1.Minute(), time1.Second(), time1.Nanosecond(), time1.Location()).UTC()
84		test(`abc = new Date(12564504e5); abc.setHours("5"); abc.toUTCString()`, time0.Format(format))
85
86		time0 = time.Date(time1.Year(), time1.Month(), 26, time1.Hour(), time1.Minute(), time1.Second(), time1.Nanosecond(), time1.Location()).UTC()
87		test(`abc = new Date(12564504e5); abc.setDate("26"); abc.toUTCString()`, time0.Format(format))
88
89		time0 = time.Date(time1.Year(), 10, time1.Day(), time1.Hour(), time1.Minute(), time1.Second(), time1.Nanosecond(), time1.Location()).UTC()
90		test(`abc = new Date(12564504e5); abc.setMonth(9); abc.toUTCString()`, time0.Format(format))
91		test(`abc = new Date(12564504e5); abc.setMonth("09"); abc.toUTCString()`, time0.Format(format))
92
93		time0 = time.Date(time1.Year(), 11, time1.Day(), time1.Hour(), time1.Minute(), time1.Second(), time1.Nanosecond(), time1.Location()).UTC()
94		test(`abc = new Date(12564504e5); abc.setMonth("10"); abc.toUTCString()`, time0.Format(format))
95
96		time0 = time.Date(2010, time1.Month(), time1.Day(), time1.Hour(), time1.Minute(), time1.Second(), time1.Nanosecond(), time1.Location()).UTC()
97		test(`abc = new Date(12564504e5); abc.setFullYear(2010); abc.toUTCString()`, time0.Format(format))
98
99		test(`new Date("2001-01-01T10:01:02.000").getTime()`, 978343262000)
100
101		// Date()
102		test(`typeof Date()`, "string")
103		test(`typeof Date(2006, 1, 2)`, "string")
104
105		test(`
106            abc = Object.getOwnPropertyDescriptor(Date, "parse");
107            [ abc.value === Date.parse, abc.writable, abc.enumerable, abc.configurable ];
108        `, "true,true,false,true")
109
110		test(`
111            abc = Object.getOwnPropertyDescriptor(Date.prototype, "toTimeString");
112            [ abc.value === Date.prototype.toTimeString, abc.writable, abc.enumerable, abc.configurable ];
113        `, "true,true,false,true")
114
115		test(`
116            var abc = Object.getOwnPropertyDescriptor(Date, "prototype");
117            [   [ typeof Date.prototype ],
118                [ abc.writable, abc.enumerable, abc.configurable ] ];
119        `, "object,false,false,false")
120	})
121}
122
123func TestDate_parse(t *testing.T) {
124	tt(t, func() {
125		test, _ := test()
126
127		defer mockUTC()()
128
129		test(`Date.parse("2001-01-01T10:01:02.000")`, 978343262000)
130
131		test(`Date.parse("2006-01-02T15:04:05.000")`, 1136214245000)
132
133		test(`Date.parse("2006")`, 1136073600000)
134
135		test(`Date.parse("1970-01-16T14:36:56+00:00")`, 1348616000)
136
137		test(`Date.parse("1970-01-16T14:36:56.313+00:00")`, 1348616313)
138
139		test(`Date.parse("1970-01-16T14:36:56.000")`, 1348616000)
140
141		test(`Date.parse.length`, 1)
142	})
143}
144
145func TestDate_UTC(t *testing.T) {
146	tt(t, func() {
147		test, _ := test()
148
149		defer mockUTC()()
150
151		test(`Date.UTC(2009, 9, 25)`, 1256428800000)
152
153		test(`Date.UTC.length`, 7)
154	})
155}
156
157func TestDate_now(t *testing.T) {
158	tt(t, func() {
159		test, _ := test()
160
161		defer mockUTC()()
162
163		// FIXME I think this too risky
164		test(`+(""+Date.now()).substr(0, 10)`, float64(epochToInteger(timeToEpoch(time.Now()))/1000))
165
166		test(`Date.now() - Date.now(1,2,3) < 24 * 60 * 60`, true)
167	})
168}
169
170func TestDate_toISOString(t *testing.T) {
171	tt(t, func() {
172		test, _ := test()
173
174		defer mockUTC()()
175
176		test(`new Date(0).toISOString()`, "1970-01-01T00:00:00.000Z")
177	})
178}
179
180func TestDate_toJSON(t *testing.T) {
181	tt(t, func() {
182		test, _ := test()
183
184		defer mockUTC()()
185
186		test(`new Date(0).toJSON()`, "1970-01-01T00:00:00.000Z")
187	})
188}
189
190func TestDate_setYear(t *testing.T) {
191	tt(t, func() {
192		test, _ := test()
193
194		defer mockUTC()()
195
196		test(`new Date(12564504e5).setYear(96)`, 846223200000)
197
198		test(`new Date(12564504e5).setYear(1996)`, 846223200000)
199
200		test(`new Date(12564504e5).setYear(2000)`, 972453600000)
201	})
202}
203
204func TestDateDefaultValue(t *testing.T) {
205	tt(t, func() {
206		test, _ := test()
207
208		defer mockUTC()()
209
210		test(`
211        var date = new Date();
212        date + 0 === date.toString() + "0";
213    `, true)
214	})
215}
216
217func TestDate_April1978(t *testing.T) {
218	tt(t, func() {
219		test, _ := test()
220
221		defer mockUTC()()
222
223		test(`
224            var abc = new Date(1978,3);
225            [ abc.getYear(), abc.getMonth(), abc.valueOf() ];
226        `, "78,3,260236800000")
227	})
228}
229
230func TestDate_setMilliseconds(t *testing.T) {
231	tt(t, func() {
232		test, _ := test()
233
234		defer mockUTC()()
235
236		test(`
237            abc = new Date();
238            def = abc.setMilliseconds();
239            [ abc, def ];
240        `, "Invalid Date,NaN")
241	})
242}
243
244func TestDate_new(t *testing.T) {
245	// FIXME?
246	// This is probably incorrect, due to differences in Go date/time handling
247	// versus ECMA date/time handling, but we'll leave this here for
248	// future reference
249
250	if true {
251		return
252	}
253
254	tt(t, func() {
255		test, _ := test()
256
257		defer mockUTC()()
258
259		test(`
260            [
261                new Date(1899, 11).valueOf(),
262                new Date(1899, 12).valueOf(),
263                new Date(1900, 0).valueOf()
264            ]
265        `, "-2211638400000,-2208960000000,-2208960000000")
266	})
267}
268
269func TestDateComparison(t *testing.T) {
270	tt(t, func() {
271		test, _ := test()
272
273		defer mockUTC()()
274
275		test(`
276            var now0 = Date.now();
277            var now1 = (new Date()).toString();
278            [ now0 === now1, Math.abs(now0 - Date.parse(now1)) <= 1000 ];
279        `, "false,true")
280	})
281}
282
283func TestDate_setSeconds(t *testing.T) {
284	tt(t, func() {
285		test, _ := test()
286
287		defer mockUTC()()
288
289		test(`
290            abc = new Date(1980, 10);
291            def = new Date(abc);
292
293            abc.setSeconds(10, 12);
294
295            def.setSeconds(10);
296            def.setMilliseconds(12);
297
298            abc.valueOf() === def.valueOf();
299        `, true)
300
301		test(`
302            abc = new Date(1980, 10);
303            def = new Date(abc);
304
305            abc.setUTCSeconds(10, 12);
306
307            def.setUTCSeconds(10);
308            def.setUTCMilliseconds(12);
309
310            abc.valueOf() === def.valueOf();
311        `, true)
312
313		test(`Date.prototype.setSeconds.length`, 2)
314		test(`Date.prototype.setUTCSeconds.length`, 2)
315	})
316}
317
318func TestDate_setMinutes(t *testing.T) {
319	tt(t, func() {
320		test, _ := test()
321
322		defer mockUTC()()
323
324		test(`
325            abc = new Date(1980, 10);
326            def = new Date(abc);
327
328            abc.setMinutes(8, 10, 12);
329
330            def.setMinutes(8);
331            def.setSeconds(10);
332            def.setMilliseconds(12);
333
334            abc.valueOf() === def.valueOf();
335        `, true)
336
337		test(`
338            abc = new Date(1980, 10);
339            def = new Date(abc);
340
341            abc.setUTCMinutes(8, 10, 12);
342
343            def.setUTCMinutes(8);
344            def.setUTCSeconds(10);
345            def.setUTCMilliseconds(12);
346
347            abc.valueOf() === def.valueOf();
348        `, true)
349
350		test(`Date.prototype.setMinutes.length`, 3)
351		test(`Date.prototype.setUTCMinutes.length`, 3)
352	})
353}
354
355func TestDate_setHours(t *testing.T) {
356	tt(t, func() {
357		test, _ := test()
358
359		defer mockUTC()()
360
361		test(`
362            abc = new Date(1980, 10);
363            def = new Date(abc);
364
365            abc.setHours(6, 8, 10, 12);
366
367            def.setHours(6);
368            def.setMinutes(8);
369            def.setSeconds(10);
370            def.setMilliseconds(12);
371
372            abc.valueOf() === def.valueOf();
373        `, true)
374
375		test(`
376            abc = new Date(1980, 10);
377            def = new Date(abc);
378
379            abc.setUTCHours(6, 8, 10, 12);
380
381            def.setUTCHours(6);
382            def.setUTCMinutes(8);
383            def.setUTCSeconds(10);
384            def.setUTCMilliseconds(12);
385
386            abc.valueOf() === def.valueOf();
387        `, true)
388
389		test(`Date.prototype.setHours.length`, 4)
390		test(`Date.prototype.setUTCHours.length`, 4)
391	})
392}
393
394func TestDate_setMonth(t *testing.T) {
395	tt(t, func() {
396		test, _ := test()
397
398		defer mockUTC()()
399
400		test(`
401            abc = new Date(1980, 10);
402            def = new Date(abc);
403
404            abc.setMonth(6, 8);
405
406            def.setMonth(6);
407            def.setDate(8);
408
409            abc.valueOf() === def.valueOf();
410        `, true)
411
412		test(`
413            abc = new Date(1980, 10);
414            def = new Date(abc);
415
416            abc.setUTCMonth(6, 8);
417
418            def.setUTCMonth(6);
419            def.setUTCDate(8);
420
421            abc.valueOf() === def.valueOf();
422        `, true)
423
424		test(`Date.prototype.setMonth.length`, 2)
425		test(`Date.prototype.setUTCMonth.length`, 2)
426	})
427}
428
429func TestDate_setFullYear(t *testing.T) {
430	tt(t, func() {
431		test, _ := test()
432
433		defer mockUTC()()
434
435		test(`
436            abc = new Date(1980, 10);
437            def = new Date(abc);
438
439            abc.setFullYear(1981, 6, 8);
440
441            def.setFullYear(1981);
442            def.setMonth(6);
443            def.setDate(8);
444
445            abc.valueOf() === def.valueOf();
446        `, true)
447
448		test(`
449            abc = new Date(1980, 10);
450            def = new Date(abc);
451
452            abc.setUTCFullYear(1981, 6, 8);
453
454            def.setUTCFullYear(1981);
455            def.setUTCMonth(6);
456            def.setUTCDate(8);
457
458            abc.valueOf() === def.valueOf();
459        `, true)
460
461		test(`Date.prototype.setFullYear.length`, 3)
462		test(`Date.prototype.setUTCFullYear.length`, 3)
463	})
464}
465
466func TestDate_setTime(t *testing.T) {
467	tt(t, func() {
468		test, _ := test()
469
470		defer mockUTC()()
471
472		test(`
473            var abc = new Date(1999, 6, 1);
474            var def = new Date();
475            def.setTime(abc.getTime());
476            [ def, abc.valueOf() == def.valueOf() ];
477        `, "Thu, 01 Jul 1999 00:00:00 UTC,true")
478
479		test(`Date.prototype.setTime.length`, 1)
480	})
481}
482