forked from sproutcore/sproutcore
-
Notifications
You must be signed in to change notification settings - Fork 0
/
datetime.js
404 lines (338 loc) · 21.4 KB
/
datetime.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
// ==========================================================================
// Project: DateTime Unit Test
// Copyright: ©2010 Martin Ottenwaelter
// ==========================================================================
/*globals module test ok equals same stop start */
module('Time');
var dt, options, ms, timezone, startTime, timezones;
module("SC.DateTime", {
setup: function() {
ms = 487054822032; // June 8, 1985, 05:00:22:32 UTC
options = { year: 1985, month: 6, day: 8, hour: 4, minute: 0, second: 22, millisecond: 32, timezone: 60 }; // an arbitrary time zone
dt = SC.DateTime.create(options);
timezones = [480, 420, 0, -60, -120, -330]; // PST, PDT, UTC, CET, CEST, Mumbai
},
teardown: function() {
dt = options = ms = timezone = startTime = null;
}
});
function timeShouldBeEqualToHash(t, h, message) {
if (h === undefined) h = options;
if (h.timezone === undefined) h.timezone = SC.DateTime.timezone;
if (message === undefined) message = "%@ of time should be equal to hash";
if (t === null) {
ok(false, 'Time should not be null');
return;
}
equals(t.get('year'), h.year , message.fmt('year'));
equals(t.get('month'), h.month, message.fmt('month'));
equals(t.get('day'), h.day, message.fmt('day'));
equals(t.get('hour'), h.hour, message.fmt('hour'));
equals(t.get('minute'), h.minute, message.fmt('minute'));
equals(t.get('second'), h.second, message.fmt('second'));
equals(t.get('millisecond'), h.millisecond, message.fmt('millisecond'));
equals(t.get('timezone'), h.timezone, message.fmt('timezone'));
}
function formatTimezone(offset) {
var modifier = offset < 0 ? '+' : '-';
offset = Math.abs(offset);
var minutes = offset % 60;
var hours = (offset - minutes) / 60;
return modifier + SC.DateTime._pad(hours) + ':' + SC.DateTime._pad(minutes);
}
test('_toMilliseconds()', function() {
var originalTimezone = options.timezone;
var originalHour = options.hour;
dt = SC.DateTime;
timezone = 300;
startTime = 1264958583000; // Sun, 31 Jan 2010 17:23:03 GMT (a randomly chosen time with which to re-init the internal date object for more robustness)
// Check the default behavior
equals(dt._toMilliseconds(null, ms, timezone), ms, "Should equal start milliseconds when no options hash provided");
equals(dt._toMilliseconds({}, ms, timezone), ms, "Should equal start milliseconds when empty options hash provided");
// Test a completely defined date/time hash with no specified start milliseconds.
equals(dt._toMilliseconds(options, null, options.timezone), ms, "Milliseconds should express the parsed options hash");
// Now specify the same time in timezone (+60), one hour west of the prime meridian.
// Pass in 'startTime' to force a reset of the internal date object so we can be sure we're not
// succeeding because of old values.
options.hour = originalHour - 1;
equals(dt._toMilliseconds(options, startTime, options.timezone + 60), ms, "Should get same milliseconds when expressing time in westerly time zone");
// Now specify the same time in timezone (-60), one hour east of the prime meridian
options.hour = originalHour + 1;
equals(dt._toMilliseconds(options, startTime, options.timezone - 60), ms, "Should get same milliseconds when expressing time in easterly time zone");
// Now start at the original 1985 time, but modify only the hour as specified in time zone 60.
options = { hour: originalHour - 1 };
equals(dt._toMilliseconds(options, ms, originalTimezone + 60, NO), ms, "Should get same result modifying only the hour as expressed in westerly time zone");
// Now do the same thing the other way
options = { hour: originalHour + 1 };
equals(dt._toMilliseconds(options, ms, originalTimezone - 60, NO), ms, "Should get same result modifying only the hour as expressed in westerly time zone");
});
test('create with a hash', function() {
timeShouldBeEqualToHash(dt, options);
});
test('create with local time milliseconds', function() {
var d = new Date(); // create a local date
var hash = { // create a hash that represents it, expressed in local time
year: d.getFullYear(),
month: d.getMonth() + 1,
day: d.getDate(),
hour: d.getHours(),
minute: d.getMinutes(),
second: d.getSeconds(),
millisecond: d.getMilliseconds(),
timezone: d.getTimezoneOffset()
};
dt = SC.DateTime.create(d.getTime()); // init a DateTime using that date's milliseconds
timeShouldBeEqualToHash(dt, hash);
// Now try creating with 0 milliseconds
equals(SC.DateTime.create(0).get('milliseconds'), 0, "Can create with 0 milliseconds");
});
test('create with default time zone', function() {
var d = new Date();
// Check that the default creation time zone is local
timezone = d.getTimezoneOffset(); // get the current location's time zone.
dt = SC.DateTime.create();
equals(dt.get('timezone'), timezone, "Default time zone should be local");
});
test('create with a hash containing milliseconds and a specified time zone', function() {
// Check that creating a predefined date from milliseconds returns the correct values
dt = SC.DateTime.create({ milliseconds: ms, timezone: options.timezone });
timeShouldBeEqualToHash(dt, options);
});
test('create with hashes expressed in various time zones', function() {
timezones.forEach(function(timezone) {
options.timezone = timezone;
dt = SC.DateTime.create(options);
timeShouldBeEqualToHash(dt, options);
});
});
test('create with default time zone', function() {
var d = new Date();
// Check that the default creation time zone is local
timezone = d.getTimezoneOffset(); // get the current location's time zone.
dt = SC.DateTime.create();
equals(dt.get('timezone'), timezone, "Default time zone should be local");
});
test('create with a hash containing milliseconds and a specified time zone', function() {
// Check that creating a predefined date from milliseconds returns the correct values
dt = SC.DateTime.create({ milliseconds: ms, timezone: options.timezone });
timeShouldBeEqualToHash(dt, options);
});
test('Adjust with hashes expressed in various time zones', function() {
timezones.forEach(function(timezone) {
var newHour;
options.timezone = timezone;
dt = SC.DateTime.create(options);
// According to Date specs, must specify all three of year, month, and date if we specify one of them,
// for the calculation to be correct. Calling adjust to change only one can have
// unpredictable results, depending on what the other two values already were.
timeShouldBeEqualToHash(dt.adjust({ year: 2005, month: 9, day: 30 }), {year: 2005, month: 9, day: 30, hour: options.hour, minute: options.minute, second: options.second, millisecond: options.millisecond, timezone: timezone});
// Setting only the hour should cascade minute, second, and millisecond to 0, etc
timeShouldBeEqualToHash(dt.adjust({ hour: 3 }), { year: options.year, month: options.month, day: options.day, hour: 3, minute: 0, second: 0, millisecond: 0, timezone: timezone});
timeShouldBeEqualToHash(dt.adjust({ minute: 1 }), { year: options.year, month: options.month, day: options.day, hour: options.hour, minute: 1, second: 0, millisecond: 0, timezone: timezone});
timeShouldBeEqualToHash(dt.adjust({ second: 12 }), { year: options.year, month: options.month, day: options.day, hour: options.hour, minute: options.minute, second: 12, millisecond: 0, timezone: timezone});
timeShouldBeEqualToHash(dt.adjust({ millisecond: 18 }), { year: options.year, month: options.month, day: options.day, hour: options.hour, minute: options.minute, second: options.second, millisecond: 18, timezone: timezone});
// Test taking each to time zone 0. Manually calculate what the hour should be
// then test that a call to get() returns that value.
newHour = Math.floor((options.hour + 48 + (timezone / 60)) % 24); // small hack -- add 48 hours to ensure positive results when adding negative time zone offsets (doesn't affect the calculation since we mod by 24)
equals(dt.adjust({ timezone: 0 }).get('hour'), newHour);
});
});
test('advance', function() {
var o = options;
timeShouldBeEqualToHash(
dt.advance({ year: 1, month: 1, day: 1, hour: 1, minute: 1, second: 1, millisecond: 1 }),
{ year: o.year + 1, month: o.month + 1, day: o.day + 1, hour: o.hour + 1, minute: o.minute + 1, second: o.second + 1, millisecond: o.millisecond + 1, timezone: o.timezone });
timeShouldBeEqualToHash(dt.advance({year: 1}), { year: o.year + 1, month: o.month, day: o.day, hour: o.hour, minute: o.minute, second: o.second, millisecond: o.millisecond, timezone: o.timezone });
timeShouldBeEqualToHash(dt.advance({month: 1}), { year: o.year, month: o.month + 1, day: o.day, hour: o.hour, minute: o.minute, second: o.second, millisecond: o.millisecond, timezone: o.timezone });
timeShouldBeEqualToHash(dt.advance({day: 1}), { year: o.year, month: o.month, day: o.day + 1, hour: o.hour, minute: o.minute, second: o.second, millisecond: o.millisecond, timezone: o.timezone });
timeShouldBeEqualToHash(dt.advance({hour: 1}), { year: o.year, month: o.month, day: o.day, hour: o.hour + 1, minute: o.minute, second: o.second, millisecond: o.millisecond, timezone: o.timezone });
timeShouldBeEqualToHash(dt.advance({minute: 1}), { year: o.year, month: o.month, day: o.day, hour: o.hour, minute: o.minute + 1, second: o.second, millisecond: o.millisecond, timezone: o.timezone });
timeShouldBeEqualToHash(dt.advance({second: 1}), { year: o.year, month: o.month, day: o.day, hour: o.hour, minute: o.minute, second: o.second + 1, millisecond: o.millisecond, timezone: o.timezone });
timeShouldBeEqualToHash(dt.advance({millisecond: 1}), { year: o.year, month: o.month, day: o.day, hour: o.hour, minute: o.minute, second: o.second, millisecond: o.millisecond + 1, timezone: o.timezone });
// Convert time from CEST to UTC, then UTC to UTC+05:30 (Mumbai)
var h = { year: 1985, month: 5, day: 8, hour: 1, minute: 0, second: 22, millisecond: 925, timezone: -120 };
var t = SC.DateTime.create(h);
timeShouldBeEqualToHash(t, h);
timeShouldBeEqualToHash(t.advance({ timezone: 120 }), { year: 1985, month: 5, day: 7, hour: 23, minute: 0, second: 22, millisecond: 925, timezone: 0 });
timeShouldBeEqualToHash(t.advance({ timezone: 120 }).advance({ timezone: -330 }), { year: 1985, month: 5, day: 8, hour: 4, minute: 30, second: 22, millisecond: 925, timezone: -330 });
equals(SC.DateTime.compare(
t.advance({ timezone: 120 }).advance({ timezone: -330 }),
t.advance({ timezone: -210 })),
0);
});
test('compare', function() {
var exception = null;
equals(SC.DateTime.isComparable, YES, "SC.DateTime is comparable");
equals(SC.compare(dt, dt), 0, "A DateTime instance is equal to itself via compare()");
equals(dt.isEqual(dt), YES, "A DateTime instance is equal to itself via isEqual()");
equals(dt.advance({hour: 1}).isEqual(dt), NO);
equals(SC.compare(dt, dt.advance({hour: 1})), -1);
equals(SC.compare(dt.advance({hour: 1}), dt), 1);
equals(SC.DateTime.compareDate(dt, dt.advance({hour: 1})), 0);
equals(SC.DateTime.compareDate(dt, dt.adjust({hour: 0}).advance({day: 1, second: -1})), 0);
equals(SC.DateTime.compareDate(dt, dt.adjust({hour: 0}).advance({day: 1})), -1);
equals(SC.DateTime.compareDate(dt, dt.advance({day: 1})), -1);
equals(SC.compare(
SC.DateTime.create({year: 1985, month: 5, day: 7, hour: 23, minute: 0, second: 22, millisecond: 925, timezone: 0}),
SC.DateTime.create({year: 1985, month: 5, day: 8, hour: 1, minute: 0, second: 22, millisecond: 925, timezone: -120})),
0, "The expressions of the same date in two different time zones are considered equal");
try {
equals(SC.DateTime.compareDate(
SC.DateTime.create({year: 1985, month: 5, day: 7, hour: 23, minute: 0, second: 22, millisecond: 925, timezone: 0}),
SC.DateTime.create({year: 1985, month: 5, day: 8, hour: 1, minute: 0, second: 22, millisecond: 925, timezone: -120})),
0);
} catch(e) {
exception = e;
} finally {
ok(!SC.none(exception), "Comparing two dates with a different timezone via compareDate() should throw an exception.");
}
});
test('Format', function() {
equals(
dt.toFormattedString('%a %A %b %B %d %D %h %H %I %j %m %M %p %S %w %y %Y %%a'),
'Sat Saturday Jun June 08 8 4 04 04 159 06 00 AM 22 6 85 1985 %a');
equals(dt.toFormattedString('%Z'), formatTimezone(dt.get('timezone')));
equals(dt.adjust({ timezone: 0 }).toFormattedString('%Y-%m-%d %H:%M:%S %Z'), '1985-06-08 05:00:22 +00:00');
equals(dt.adjust({ timezone: -120 }).toFormattedString('%Y-%m-%d %H:%M:%S %Z'), '1985-06-08 07:00:22 +02:00');
equals(dt.adjust({ timezone: 420 }).toFormattedString('%Y-%m-%d %H:%M:%S %Z'), '1985-06-07 22:00:22 -07:00'); // the previous day
});
test('fancy getters', function() {
equals(dt.get('isLeapYear'), NO);
// (note must set all three components of a date
// in order to get predictable results, per JS Date object spec)
equals(SC.DateTime.create({ year: 1900, month: 1, day: 1 }).get('isLeapYear'), NO);
equals(SC.DateTime.create({ year: 2000, month: 1, day: 1 }).get('isLeapYear'), YES);
equals(SC.DateTime.create({ year: 2004, month: 1, day: 1 }).get('isLeapYear'), YES);
equals(dt.get('daysInMonth'), 30); // june
equals(SC.DateTime.create({ year: 2000, month: 2, day: 1 }).get('daysInMonth'), 29);
equals(SC.DateTime.create({ year: 2001, month: 2, day: 1 }).get('daysInMonth'), 28);
equals(dt.get('dayOfYear'), 159);
equals(SC.DateTime.create({ year: 2000, month: 12, day: 31 }).get('dayOfYear'), 366);
equals(SC.DateTime.create({ year: 2001, month: 12, day: 31 }).get('dayOfYear'), 365);
equals(dt.get('week'), 22);
equals(SC.DateTime.create({ year: 2006, month: 1, day: 1 }).get('week0'), 1);
equals(SC.DateTime.create({ year: 2006, month: 1, day: 1 }).get('week1'), 0);
equals(SC.DateTime.create({ year: 2006, month: 1, day: 8 }).get('week0'), 2);
equals(SC.DateTime.create({ year: 2006, month: 1, day: 8 }).get('week1'), 1);
equals(SC.DateTime.create({ year: 2006, month: 12, day: 31 }).get('week0'), 53);
equals(SC.DateTime.create({ year: 2006, month: 12, day: 31 }).get('week1'), 52);
equals(dt.get('lastMonday'), dt.advance({ day: -5 }), 'dt.advance(day: -5)');
equals(dt.get('nextFriday'), dt.advance({ day: 6 }), 'dt.advance(day: 6)');
equals(dt.get('lastWednesday'), dt.advance({ day: -3 }), 'dt.advance(day: -3)');
equals(
SC.DateTime.create({ year: 2010, month: 9, day: 29, hour: 0, minute: 30, timezone: -120 }).adjust({ day: 1 }).get('lastMonday').toISO8601(),
"2010-08-30T00:30:00+02:00");
});
test('parse', function() {
timeShouldBeEqualToHash(
SC.DateTime.parse('08/05/1985 01:00:22 %a', '%d/%m/%Y %H:%M:%S %%a'),
{ year: 1985, month: 5, day: 8, hour: 1, minute: 0, second: 22, millisecond: 0 });
timeShouldBeEqualToHash(
SC.DateTime.parse('08/05/1985 01:00:22 PM', '%d/%m/%Y %H:%M:%S %p'),
{ year: 1985, month: 5, day: 8, hour: 13, minute: 0, second: 22, millisecond: 0 });
timeShouldBeEqualToHash(
SC.DateTime.parse('Wed 08 May 1985 01:00:22 AM', '%a %d %b %Y %H:%M:%S %p'),
{ year: 1985, month: 5, day: 8, hour: 1, minute: 0, second: 22, millisecond: 0 });
ok(
SC.DateTime.parse('Tue 08 May 1985 01:00:22 AM', '%a %d %b %Y %H:%M:%S %p')
=== null, '1985-05-08 is not a tuesday');
ok(
SC.DateTime.parse('07/01/20201 18:33:22 %a Z', '%d/%m/%Y %H:%M:%S %%a %Z') === null &&
SC.DateTime.parse('07/01/20201 18:33:22 %a Z', '%d/%m/%Y %H:%M:%S %%a %Z') === null &&
SC.DateTime.parse('07/01/20201 18:33:22 %a Z', '%d/%m/%Y %H:%M:%S %%a %Z') === null &&
SC.DateTime.parse('07/01/20201 18:33:22 %a Z', '%d/%m/%Y %H:%M:%S %%a %Z') === null &&
SC.DateTime.parse('07/01/20201 18:33:22 %a Z', '%d/%m/%Y %H:%M:%S %%a %Z') === null &&
SC.DateTime.parse('07/01/20201 18:33:22 %a Z', '%d/%m/%Y %H:%M:%S %%a %Z') === null &&
SC.DateTime.parse('07/01/20201 18:33:22 %a Z', '%d/%m/%Y %H:%M:%S %%a %Z') === null &&
SC.DateTime.parse('07/01/20201 18:33:22 %a Z', '%d/%m/%Y %H:%M:%S %%a %Z') === null &&
SC.DateTime.parse('07/01/20201 18:33:22 %a Z', '%d/%m/%Y %H:%M:%S %%a %Z') === null
, 'Should be able to fail to parse multiple times');
timeShouldBeEqualToHash(
SC.DateTime.parse('1/1/01 0:0:0', '%m/%d/%y %H:%M:%S'),
{ year: 2001, month: 1, day: 1, hour: 0, minute: 0, second: 0, millisecond: 0 },
'Should be able to have single digit for month, day, hour, minute, second');
timeShouldBeEqualToHash(
SC.DateTime.parse('70-01-01 00:00:00', '%y-%m-%d %H:%M:%S'),
{ year: 2070, month: 1, day: 1, hour: 0, minute: 0, second: 0, millisecond: 0 });
timeShouldBeEqualToHash(
SC.DateTime.parse('71-01-01 00:00:00', '%y-%m-%d %H:%M:%S'),
{ year: 1971, month: 1, day: 1, hour: 0, minute: 0, second: 0, millisecond: 0 });
timeShouldBeEqualToHash(
SC.DateTime.parse('71-01-01 12:00 AM', '%y-%m-%d %i:%M %p'),
{ year: 1971, month: 1, day: 1, hour: 0, minute: 0, second: 0, millisecond: 0 });
timeShouldBeEqualToHash(
SC.DateTime.parse('71-01-01 12:00 PM', '%y-%m-%d %i:%M %p'),
{ year: 1971, month: 1, day: 1, hour: 12, minute: 0, second: 0, millisecond: 0 });
});
test('parse with time zones',function() {
equals(
SC.DateTime.parse('08/05/1985 01:00:22 %a -0700', '%d/%m/%Y %H:%M:%S %%a %Z').toISO8601(),
"1985-05-08T01:00:22-07:00");
equals(
SC.DateTime.parse('08/05/1985 01:00:22 %a +02:00', '%d/%m/%Y %H:%M:%S %%a %Z').toISO8601(),
"1985-05-08T01:00:22+02:00");
equals(
SC.DateTime.parse('07/01/2020 18:33:22 %a Z', '%d/%m/%Y %H:%M:%S %%a %Z').toISO8601(),
"2020-01-07T18:33:22+00:00");
});
test('parse without a format uses default ISO8601', function() {
equals(SC.DateTime.parse("2010-09-17T18:35:08Z").toISO8601(), "2010-09-17T18:35:08+00:00");
});
test('parse with hours and meridian', function(){
equals(SC.DateTime.parse("03/25/2011 5:12:50PM Z", "%m/%d/%Y %I:%M:%S%p %Z").toISO8601(), "2011-03-25T17:12:50+00:00");
equals(SC.DateTime.parse("03/25/2011 5:12:50PM Z", "%m/%d/%Y %i:%M:%S%p %Z").toISO8601(), "2011-03-25T17:12:50+00:00");
equals(SC.DateTime.parse("03/25/2011 05:12:50PM Z", "%m/%d/%Y %I:%M:%S%p %Z").toISO8601(), "2011-03-25T17:12:50+00:00");
equals(SC.DateTime.parse("03/25/2011 05:12:50PM Z", "%m/%d/%Y %i:%M:%S%p %Z").toISO8601(), "2011-03-25T17:12:50+00:00");
});
test('bad parsing', function() {
equals(SC.DateTime.parse(SC.DateTime.parse("foo")), null);
equals(SC.DateTime.parse("2010-09-17T18:35:08Z", SC.DATETIME_ISO8601).toISO8601(), "2010-09-17T18:35:08+00:00");
});
test('binding', function() {
var fromObject = SC.Object.create({value: dt});
var toObject = SC.Object.create({value: ''});
var format = '%Y-%m-%d %H:%M:%S';
var binding = SC.Binding.dateTime(format).from('value', fromObject).to('value', toObject).connect();
SC.Binding.flushPendingChanges();
equals(toObject.get('value'), dt.toFormattedString(format));
});
test('cache', function() {
SC.DateTime.create(options);
var cache_length_1 = SC.keys(SC.DateTime._dt_cache).length;
SC.DateTime.create(options);
var cache_length_2 = SC.keys(SC.DateTime._dt_cache).length;
equals(
cache_length_1, cache_length_2,
"Creating twice the same datetime should not modify the cache's length");
var dates = [];
for (var i = 0; i < 3*SC.DateTime._DT_CACHE_MAX_LENGTH; i++) {
dates[i] = SC.DateTime.create(i);
}
ok(
SC.keys(SC.DateTime._dt_cache).length <= 2*SC.DateTime._DT_CACHE_MAX_LENGTH,
"Creating a lot of datetimes should not make a cache larger than the maximum allowed size");
});
test('timezones', function() {
var o = options;
options.timezone = 0;
timeShouldBeEqualToHash(SC.DateTime.create(options), options);
options.timezone = -120;
timeShouldBeEqualToHash(SC.DateTime.create(options), options);
options.timezone = 330;
timeShouldBeEqualToHash(SC.DateTime.create(options), options);
options.timezone = 0; // note that test dates will now be created at timezone 0
dt = SC.DateTime.create(options);
timeShouldBeEqualToHash(dt, {year: o.year, month: o.month, day: o.day, hour: o.hour, minute: o.minute, second: o.second, millisecond: o.millisecond, timezone: o.timezone });
timeShouldBeEqualToHash(dt.toTimezone(480), {year: o.year, month: o.month, day: o.day - 1, hour: 20, minute: o.minute, second: o.second, millisecond: o.millisecond, timezone: 480 });
timeShouldBeEqualToHash(dt.toTimezone(420), {year: o.year, month: o.month, day: o.day - 1, hour: 21, minute: o.minute, second: o.second, millisecond: o.millisecond, timezone: 420 });
timeShouldBeEqualToHash(dt.toTimezone(), {year: o.year, month: o.month, day: o.day, hour: o.hour, minute: o.minute, second: o.second, millisecond: o.millisecond, timezone: 0 });
timeShouldBeEqualToHash(dt.toTimezone(-60), {year: o.year, month: o.month, day: o.day, hour: 5, minute: o.minute, second: o.second, millisecond: o.millisecond, timezone: -60 });
timeShouldBeEqualToHash(dt.toTimezone(-120), {year: o.year, month: o.month, day: o.day, hour: 6, minute: o.minute, second: o.second, millisecond: o.millisecond, timezone: -120 });
timeShouldBeEqualToHash(dt.toTimezone(-330), {year: o.year, month: o.month, day: o.day, hour: 9, minute: 30, second: o.second, millisecond: o.millisecond, timezone: -330 });
});
test('extend', function() {
var dateTimeExt = SC.DateTime.extend();
// Should parse and produce a date object that is an instance of 'dateTimeExt'
var parsedDateTimeExt = dateTimeExt.parse('2011-10-15T21:30:00Z');
ok(SC.instanceOf(parsedDateTimeExt, dateTimeExt), 'Correctly produced an instance of the extended type.');
});