The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / date-delay.js @ 40c0f755

History | View | Annotate | Download (28.2 KB)

1
// Copyright 2006-2008 the V8 project authors. All rights reserved.
2
// Redistribution and use in source and binary forms, with or without
3
// modification, are permitted provided that the following conditions are
4
// met:
5
//
6
//     * Redistributions of source code must retain the above copyright
7
//       notice, this list of conditions and the following disclaimer.
8
//     * Redistributions in binary form must reproduce the above
9
//       copyright notice, this list of conditions and the following
10
//       disclaimer in the documentation and/or other materials provided
11
//       with the distribution.
12
//     * Neither the name of Google Inc. nor the names of its
13
//       contributors may be used to endorse or promote products derived
14
//       from this software without specific prior written permission.
15
//
16
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27

    
28

    
29
// This file relies on the fact that the following declarations have been made
30
// in v8natives.js:
31
// const $isNaN = GlobalIsNaN;
32
// const $isFinite = GlobalIsFinite;
33

    
34
// -------------------------------------------------------------------
35

    
36
// This file contains date support implemented in JavaScript.
37

    
38

    
39
// Keep reference to original values of some global properties.  This
40
// has the added benefit that the code in this file is isolated from
41
// changes to these properties.
42
const $Date = global.Date;
43

    
44
// ECMA 262 - 15.9.1.2
45
function Day(time) {
46
  return FLOOR(time/msPerDay);
47
}
48

    
49

    
50
// ECMA 262 - 5.2
51
function Modulo(value, remainder) {
52
  var mod = value % remainder;
53
  // Guard against returning -0.
54
  if (mod == 0) return 0;
55
  return mod >= 0 ? mod : mod + remainder;
56
}
57

    
58

    
59
function TimeWithinDay(time) {
60
  return Modulo(time, msPerDay);
61
}
62

    
63

    
64
// ECMA 262 - 15.9.1.3
65
function DaysInYear(year) {
66
  if (year % 4 != 0) return 365;
67
  if ((year % 100 == 0) && (year % 400 != 0)) return 365;
68
  return 366;
69
}
70

    
71

    
72
function DayFromYear(year) {
73
  return 365 * (year-1970)
74
      + FLOOR((year-1969)/4)
75
      - FLOOR((year-1901)/100)
76
      + FLOOR((year-1601)/400);
77
}
78

    
79

    
80
function TimeFromYear(year) {
81
  return msPerDay * DayFromYear(year);
82
}
83

    
84

    
85
function YearFromTime(time) {
86
  return FromJulianDay(Day(time) + kDayZeroInJulianDay).year;
87
}
88

    
89

    
90
function InLeapYear(time) {
91
  return DaysInYear(YearFromTime(time)) == 366 ? 1 : 0;
92
}
93

    
94

    
95
// ECMA 262 - 15.9.1.4
96
function MonthFromTime(time) {
97
  return FromJulianDay(Day(time) + kDayZeroInJulianDay).month;
98
}
99

    
100

    
101
function DayWithinYear(time) {
102
  return Day(time) - DayFromYear(YearFromTime(time));
103
}
104

    
105

    
106
// ECMA 262 - 15.9.1.5
107
function DateFromTime(time) {
108
  return FromJulianDay(Day(time) + kDayZeroInJulianDay).date;
109
}
110

    
111

    
112
// ECMA 262 - 15.9.1.9
113
function EquivalentYear(year) {
114
  // Returns an equivalent year in the range [2008-2035] matching
115
  // - leap year.
116
  // - week day of first day.
117
  var time = TimeFromYear(year);
118
  var recent_year = (InLeapYear(time) == 0 ? 1967 : 1956) + 
119
      (WeekDay(time) * 12) % 28;
120
  // Find the year in the range 2008..2037 that is equivalent mod 28.
121
  // Add 3*28 to give a positive argument to the modulus operator.
122
  return 2008 + (recent_year + 3*28 - 2008) % 28;
123
}
124

    
125

    
126
function EquivalentTime(t) {
127
  // The issue here is that some library calls don't work right for dates
128
  // that cannot be represented using a non-negative signed 32 bit integer
129
  // (measured in whole seconds based on the 1970 epoch).
130
  // We solve this by mapping the time to a year with same leap-year-ness
131
  // and same starting day for the year.  The ECMAscript specification says
132
  // we must do this, but for compatability with other browsers, we use
133
  // the actual year if it is in the range 1970..2037
134
  if (t >= 0 && t <= 2.1e12) return t;
135
  var day = MakeDay(EquivalentYear(YearFromTime(t)), MonthFromTime(t), DateFromTime(t));
136
  return TimeClip(MakeDate(day, TimeWithinDay(t)));
137
}
138

    
139
var daylight_cache_time = $NaN;
140
var daylight_cache_offset;
141

    
142
function DaylightSavingsOffset(t) {
143
  if (t == daylight_cache_time) {
144
    return daylight_cache_offset;
145
  }
146
  var offset = %DateDaylightSavingsOffset(EquivalentTime(t));
147
  daylight_cache_time = t;
148
  daylight_cache_offset = offset;
149
  return offset;
150
}
151

    
152

    
153
var timezone_cache_time = $NaN;
154
var timezone_cache_timezone;
155

    
156
function LocalTimezone(t) {
157
  if(t == timezone_cache_time) {
158
    return timezone_cache_timezone;
159
  }
160
  var timezone = %DateLocalTimezone(EquivalentTime(t));
161
  timezone_cache_time = t;
162
  timezone_cache_timezone = timezone;
163
  return timezone;
164
}
165

    
166

    
167
function WeekDay(time) {
168
  return Modulo(Day(time) + 4, 7);
169
}
170

    
171
var local_time_offset = %DateLocalTimeOffset();
172

    
173
function LocalTime(time) {
174
  if ($isNaN(time)) return time;
175
  return time + local_time_offset + DaylightSavingsOffset(time);
176
}
177

    
178
function LocalTimeNoCheck(time) {
179
  return time + local_time_offset + DaylightSavingsOffset(time);
180
}
181

    
182

    
183
function UTC(time) {
184
  if ($isNaN(time)) return time;
185
  var tmp = time - local_time_offset;
186
  return tmp - DaylightSavingsOffset(tmp);
187
}
188

    
189

    
190
// ECMA 262 - 15.9.1.10
191
function HourFromTime(time) {
192
  return Modulo(FLOOR(time / msPerHour), HoursPerDay);
193
}
194

    
195

    
196
function MinFromTime(time) {
197
  return Modulo(FLOOR(time / msPerMinute), MinutesPerHour);
198
}
199

    
200

    
201
function SecFromTime(time) {
202
  return Modulo(FLOOR(time / msPerSecond), SecondsPerMinute);
203
}
204

    
205

    
206
function msFromTime(time) {
207
  return Modulo(time, msPerSecond);
208
}
209

    
210

    
211
// ECMA 262 - 15.9.1.11
212
function MakeTime(hour, min, sec, ms) {
213
  if (!$isFinite(hour)) return $NaN;
214
  if (!$isFinite(min)) return $NaN;
215
  if (!$isFinite(sec)) return $NaN;
216
  if (!$isFinite(ms)) return $NaN;
217
  return TO_INTEGER(hour) * msPerHour
218
      + TO_INTEGER(min) * msPerMinute
219
      + TO_INTEGER(sec) * msPerSecond
220
      + TO_INTEGER(ms);
221
}
222

    
223

    
224
// ECMA 262 - 15.9.1.12
225
function TimeInYear(year) {
226
  return DaysInYear(year) * msPerDay;
227
}
228

    
229

    
230
// Compute modified Julian day from year, month, date.
231
function ToJulianDay(year, month, date) {
232
  var jy = (month > 1) ? year : year - 1;
233
  var jm = (month > 1) ? month + 2 : month + 14;
234
  var ja = FLOOR(jy / 100);
235
  return FLOOR(FLOOR(365.25*jy) + FLOOR(30.6001*jm) + date + 1720995) + 2 - ja + FLOOR(0.25*ja);
236
}
237

    
238
var four_year_cycle_table = CalculateDateTable();
239

    
240

    
241
function CalculateDateTable() {
242
  var month_lengths = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
243
  var four_year_cycle_table = new $Array(1461);
244

    
245
  var cumulative = 0;
246
  var position = 0;
247
  var leap_position = 0;
248
  for (var month = 0; month < 12; month++) {
249
    var month_bits = month << kMonthShift;
250
    var length = month_lengths[month];
251
    for (var day = 1; day <= length; day++) {
252
      four_year_cycle_table[leap_position] =
253
        month_bits + day;
254
      four_year_cycle_table[366 + position] =
255
        (1 << kYearShift) + month_bits + day;
256
      four_year_cycle_table[731 + position] =
257
        (2 << kYearShift) + month_bits + day;
258
      four_year_cycle_table[1096 + position] =
259
        (3 << kYearShift) + month_bits + day;
260
      leap_position++;
261
      position++;
262
    }
263
    if (month == 1) {
264
      four_year_cycle_table[leap_position++] = month_bits + 29;
265
    }
266
  }
267
  return four_year_cycle_table;
268
}
269

    
270

    
271
// Constructor for creating objects holding year, month, and date.
272
// Introduced to ensure the two return points in FromJulianDay match same map.
273
function DayTriplet(year, month, date) {
274
  this.year = year;
275
  this.month = month;
276
  this.date = date;
277
}
278

    
279
var julian_day_cache_triplet;
280
var julian_day_cache_day = $NaN;
281

    
282
// Compute year, month, and day from modified Julian day.
283
// The missing days in 1582 are ignored for JavaScript compatibility.
284
function FromJulianDay(julian) {
285
  if (julian_day_cache_day == julian) {
286
    return julian_day_cache_triplet;
287
  }
288
  var result;
289
  // Avoid floating point and non-Smi maths in common case.  This is also a period of
290
  // time where leap years are very regular.  The range is not too large to avoid overflow
291
  // when doing the multiply-to-divide trick.
292
  if (julian > kDayZeroInJulianDay &&
293
      (julian - kDayZeroInJulianDay) < 40177) { // 1970 - 2080
294
    var jsimple = (julian - kDayZeroInJulianDay) + 731; // Day 0 is 1st January 1968
295
    var y = 1968;
296
    // Divide by 1461 by multiplying with 22967 and shifting down by 25!
297
    var after_1968 = (jsimple * 22967) >> 25;
298
    y += after_1968 << 2;
299
    jsimple -= 1461 * after_1968;
300
    var four_year_cycle = four_year_cycle_table[jsimple];
301
    result = new DayTriplet(y + (four_year_cycle >> kYearShift),
302
                            (four_year_cycle & kMonthMask) >> kMonthShift,
303
                            four_year_cycle & kDayMask);
304
  } else {
305
    var jalpha = FLOOR((julian - 1867216.25) / 36524.25);
306
    var jb = julian + 1 + jalpha - FLOOR(0.25 * jalpha) + 1524;
307
    var jc = FLOOR(6680.0 + ((jb-2439870) - 122.1)/365.25);
308
    var jd = FLOOR(365 * jc + (0.25 * jc));
309
    var je = FLOOR((jb - jd)/30.6001);
310
    var m = je - 1;
311
    if (m > 12) m -= 13;
312
    var y = jc - 4715;
313
    if (m > 2) { --y; --m; }
314
    var d = jb - jd - FLOOR(30.6001 * je);
315
    result = new DayTriplet(y, m, d);
316
  }
317
  julian_day_cache_day = julian;
318
  julian_day_cache_triplet = result;
319
  return result;
320
}
321

    
322

    
323
// Compute number of days given a year, month, date.
324
// Note that month and date can lie outside the normal range.
325
//   For example:
326
//     MakeDay(2007, -4, 20) --> MakeDay(2006, 8, 20)
327
//     MakeDay(2007, -33, 1) --> MakeDay(2004, 3, 1)
328
//     MakeDay(2007, 14, -50) --> MakeDay(2007, 8, 11)
329
function MakeDay(year, month, date) {
330
  if (!$isFinite(year) || !$isFinite(month) || !$isFinite(date)) return $NaN;
331

    
332
  // Conversion to integers.
333
  year = TO_INTEGER(year);
334
  month = TO_INTEGER(month);
335
  date = TO_INTEGER(date);
336

    
337
  // Overflow months into year.
338
  year = year + FLOOR(month/12);
339
  month = month % 12;
340
  if (month < 0) {
341
    month += 12;
342
  }
343

    
344
  // Return days relative to Jan 1 1970.
345
  return ToJulianDay(year, month, date) - kDayZeroInJulianDay;
346
}
347

    
348

    
349
// ECMA 262 - 15.9.1.13
350
function MakeDate(day, time) {
351
  if (!$isFinite(day)) return $NaN;
352
  if (!$isFinite(time)) return $NaN;
353
  return day * msPerDay + time;
354
}
355

    
356

    
357
// ECMA 262 - 15.9.1.14
358
function TimeClip(time) {
359
  if (!$isFinite(time)) return $NaN;
360
  if ($abs(time) > 8.64E15) return $NaN;
361
  return TO_INTEGER(time);
362
}
363

    
364

    
365
%SetCode($Date, function(year, month, date, hours, minutes, seconds, ms) {
366
  if (%IsConstructCall()) {
367
    // ECMA 262 - 15.9.3
368
    var argc = %_ArgumentsLength();
369
    if (argc == 0) {
370
      %_SetValueOf(this, %DateCurrentTime());
371
      return;
372
    }
373
    if (argc == 1) {
374
      // According to ECMA 262, no hint should be given for this
375
      // conversion.  However, ToPrimitive defaults to String Hint
376
      // for Date objects which will lose precision when the Date
377
      // constructor is called with another Date object as its
378
      // argument.  We therefore use Number Hint for the conversion
379
      // (which is the default for everything else than Date
380
      // objects).  This makes us behave like KJS and SpiderMonkey.
381
      var time = ToPrimitive(year, NUMBER_HINT);
382
      if (IS_STRING(time)) {
383
        %_SetValueOf(this, DateParse(time));
384
      } else {
385
        %_SetValueOf(this, TimeClip(ToNumber(time)));
386
      }
387
      return;
388
    }
389
    year = ToNumber(year);
390
    month = ToNumber(month);
391
    date = argc > 2 ? ToNumber(date) : 1;
392
    hours = argc > 3 ? ToNumber(hours) : 0;
393
    minutes = argc > 4 ? ToNumber(minutes) : 0;
394
    seconds = argc > 5 ? ToNumber(seconds) : 0;
395
    ms = argc > 6 ? ToNumber(ms) : 0;
396
    year = (!$isNaN(year) && 0 <= TO_INTEGER(year) && TO_INTEGER(year) <= 99)
397
        ? 1900 + TO_INTEGER(year) : year;
398
    var day = MakeDay(year, month, date);
399
    var time = MakeTime(hours, minutes, seconds, ms);
400
    %_SetValueOf(this, TimeClip(UTC(MakeDate(day, time))));
401
  } else {
402
    // ECMA 262 - 15.9.2
403
    return (new $Date()).toString();
404
  }
405
});
406

    
407

    
408
// Helper functions.
409
function GetTimeFrom(aDate) {
410
  if (IS_DATE(aDate)) return %_ValueOf(aDate);
411
  throw new $TypeError('this is not a Date object.');
412
}
413

    
414

    
415
function GetMillisecondsFrom(aDate) {
416
  var t = GetTimeFrom(aDate);
417
  if ($isNaN(t)) return t;
418
  return msFromTime(LocalTimeNoCheck(t));
419
}
420

    
421

    
422
function GetUTCMillisecondsFrom(aDate) {
423
  var t = GetTimeFrom(aDate);
424
  if ($isNaN(t)) return t;
425
  return msFromTime(t);
426
}
427

    
428

    
429
function GetSecondsFrom(aDate) {
430
  var t = GetTimeFrom(aDate);
431
  if ($isNaN(t)) return t;
432
  return SecFromTime(LocalTimeNoCheck(t));
433
}
434

    
435

    
436
function GetUTCSecondsFrom(aDate) {
437
  var t = GetTimeFrom(aDate);
438
  if ($isNaN(t)) return t;
439
  return SecFromTime(t);
440
}
441

    
442

    
443
function GetMinutesFrom(aDate) {
444
  var t = GetTimeFrom(aDate);
445
  if ($isNaN(t)) return t;
446
  return MinFromTime(LocalTimeNoCheck(t));
447
}
448

    
449

    
450
function GetUTCMinutesFrom(aDate) {
451
  var t = GetTimeFrom(aDate);
452
  if ($isNaN(t)) return t;
453
  return MinFromTime(t);
454
}
455

    
456

    
457
function GetHoursFrom(aDate) {
458
  var t = GetTimeFrom(aDate);
459
  if ($isNaN(t)) return t;
460
  return HourFromTime(LocalTimeNoCheck(t));
461
}
462

    
463

    
464
function GetUTCHoursFrom(aDate) {
465
  var t = GetTimeFrom(aDate);
466
  if ($isNaN(t)) return t;
467
  return HourFromTime(t);
468
}
469

    
470

    
471
function GetFullYearFrom(aDate) {
472
  var t = GetTimeFrom(aDate);
473
  if ($isNaN(t)) return t;
474
  return YearFromTime(LocalTimeNoCheck(t));
475
}
476

    
477

    
478
function GetUTCFullYearFrom(aDate) {
479
  var t = GetTimeFrom(aDate);
480
  if ($isNaN(t)) return t;
481
  return YearFromTime(t);
482
}
483

    
484

    
485
function GetMonthFrom(aDate) {
486
  var t = GetTimeFrom(aDate);
487
  if ($isNaN(t)) return t;
488
  return MonthFromTime(LocalTimeNoCheck(t));
489
}
490

    
491

    
492
function GetUTCMonthFrom(aDate) {
493
  var t = GetTimeFrom(aDate);
494
  if ($isNaN(t)) return t;
495
  return MonthFromTime(t);
496
}
497

    
498

    
499
function GetDateFrom(aDate) {
500
  var t = GetTimeFrom(aDate);
501
  if ($isNaN(t)) return t;
502
  return DateFromTime(LocalTimeNoCheck(t));
503
}
504

    
505

    
506
function GetUTCDateFrom(aDate) {
507
  var t = GetTimeFrom(aDate);
508
  if ($isNaN(t)) return t;
509
  return DateFromTime(t);
510
}
511

    
512

    
513
%FunctionSetPrototype($Date, new $Date($NaN));
514

    
515

    
516
var WeekDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
517
var Months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
518

    
519

    
520
function TwoDigitString(value) {
521
  return value < 10 ? "0" + value : "" + value;
522
}
523

    
524

    
525
function DateString(time) {
526
  var YMD = FromJulianDay(Day(time) + kDayZeroInJulianDay);
527
  return WeekDays[WeekDay(time)] + ' '
528
      + Months[YMD.month] + ' '
529
      + TwoDigitString(YMD.date) + ' '
530
      + YMD.year;
531
}
532

    
533

    
534
var LongWeekDays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
535
var LongMonths = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
536

    
537

    
538
function LongDateString(time) {
539
  var YMD = FromJulianDay(Day(time) + kDayZeroInJulianDay);
540
  return LongWeekDays[WeekDay(time)] + ', '
541
      + LongMonths[YMD.month] + ' '
542
      + TwoDigitString(YMD.date) + ', '
543
      + YMD.year;
544
}
545

    
546

    
547
function TimeString(time) {
548
  return TwoDigitString(HourFromTime(time)) + ':'
549
      + TwoDigitString(MinFromTime(time)) + ':'
550
      + TwoDigitString(SecFromTime(time));
551
}
552

    
553

    
554
function LocalTimezoneString(time) {
555
  var timezoneOffset = (local_time_offset + DaylightSavingsOffset(time)) / msPerMinute;
556
  var sign = (timezoneOffset >= 0) ? 1 : -1;
557
  var hours = FLOOR((sign * timezoneOffset)/60);
558
  var min   = FLOOR((sign * timezoneOffset)%60);
559
  var gmt = ' GMT' + ((sign == 1) ? '+' : '-') + TwoDigitString(hours) + TwoDigitString(min);
560
  return gmt + ' (' +  LocalTimezone(time) + ')';
561
}
562

    
563

    
564
function DatePrintString(time) {
565
  return DateString(time) + ' ' + TimeString(time);
566
}
567

    
568
// -------------------------------------------------------------------
569

    
570
// Reused output buffer.
571
var parse_buffer = $Array(7);
572

    
573
// ECMA 262 - 15.9.4.2
574
function DateParse(string) {
575
  var arr = %DateParseString(ToString(string), parse_buffer);
576
  if (IS_NULL(arr)) return $NaN;
577

    
578
  var day = MakeDay(arr[0], arr[1], arr[2]);
579
  var time = MakeTime(arr[3], arr[4], arr[5], 0);
580
  var date = MakeDate(day, time);
581

    
582
  if (IS_NULL(arr[6])) {
583
    return TimeClip(UTC(date));
584
  } else {
585
    return TimeClip(date - arr[6] * 1000);
586
  }
587
}
588

    
589

    
590
// ECMA 262 - 15.9.4.3
591
function DateUTC(year, month, date, hours, minutes, seconds, ms) {
592
  year = ToNumber(year);
593
  month = ToNumber(month);
594
  var argc = %_ArgumentsLength();
595
  date = argc > 2 ? ToNumber(date) : 1;
596
  hours = argc > 3 ? ToNumber(hours) : 0;
597
  minutes = argc > 4 ? ToNumber(minutes) : 0;
598
  seconds = argc > 5 ? ToNumber(seconds) : 0;
599
  ms = argc > 6 ? ToNumber(ms) : 0;
600
  year = (!$isNaN(year) && 0 <= TO_INTEGER(year) && TO_INTEGER(year) <= 99)
601
      ? 1900 + TO_INTEGER(year) : year;
602
  var day = MakeDay(year, month, date);
603
  var time = MakeTime(hours, minutes, seconds, ms);
604
  return %_SetValueOf(this, TimeClip(MakeDate(day, time)));
605
}
606

    
607

    
608
// Mozilla-specific extension. Returns the number of milliseconds
609
// elapsed since 1 January 1970 00:00:00 UTC.
610
function DateNow() {
611
  return %DateCurrentTime();
612
}
613

    
614

    
615
// ECMA 262 - 15.9.5.2
616
function DateToString() {
617
  var t = GetTimeFrom(this);
618
  if ($isNaN(t)) return kInvalidDate;
619
  return DatePrintString(LocalTimeNoCheck(t)) + LocalTimezoneString(t);
620
}
621

    
622

    
623
// ECMA 262 - 15.9.5.3
624
function DateToDateString() {
625
  var t = GetTimeFrom(this);
626
  if ($isNaN(t)) return kInvalidDate;
627
  return DateString(LocalTimeNoCheck(t));
628
}
629

    
630

    
631
// ECMA 262 - 15.9.5.4
632
function DateToTimeString() {
633
  var t = GetTimeFrom(this);
634
  if ($isNaN(t)) return kInvalidDate;
635
  var lt = LocalTimeNoCheck(t);
636
  return TimeString(lt) + LocalTimezoneString(lt);
637
}
638

    
639

    
640
// ECMA 262 - 15.9.5.5
641
function DateToLocaleString() {
642
  return DateToString.call(this);
643
}
644

    
645

    
646
// ECMA 262 - 15.9.5.6
647
function DateToLocaleDateString() {
648
  var t = GetTimeFrom(this);
649
  if ($isNaN(t)) return kInvalidDate;
650
  return LongDateString(LocalTimeNoCheck(t));
651
}
652

    
653

    
654
// ECMA 262 - 15.9.5.7
655
function DateToLocaleTimeString() {
656
  var t = GetTimeFrom(this);
657
  if ($isNaN(t)) return kInvalidDate;
658
  var lt = LocalTimeNoCheck(t);
659
  return TimeString(lt);
660
}
661

    
662

    
663
// ECMA 262 - 15.9.5.8
664
function DateValueOf() {
665
  return GetTimeFrom(this);
666
}
667

    
668

    
669
// ECMA 262 - 15.9.5.9
670
function DateGetTime() {
671
  return GetTimeFrom(this);
672
}
673

    
674

    
675
// ECMA 262 - 15.9.5.10
676
function DateGetFullYear() {
677
  return GetFullYearFrom(this)
678
}
679

    
680

    
681
// ECMA 262 - 15.9.5.11
682
function DateGetUTCFullYear() {
683
  return GetUTCFullYearFrom(this)
684
}
685

    
686

    
687
// ECMA 262 - 15.9.5.12
688
function DateGetMonth() {
689
  return GetMonthFrom(this);
690
}
691

    
692

    
693
// ECMA 262 - 15.9.5.13
694
function DateGetUTCMonth() {
695
  return GetUTCMonthFrom(this);
696
}
697

    
698

    
699
// ECMA 262 - 15.9.5.14
700
function DateGetDate() {
701
  return GetDateFrom(this);
702
}
703

    
704

    
705
// ECMA 262 - 15.9.5.15
706
function DateGetUTCDate() {
707
  return GetUTCDateFrom(this);
708
}
709

    
710

    
711
// ECMA 262 - 15.9.5.16
712
function DateGetDay() {
713
  var t = GetTimeFrom(this);
714
  if ($isNaN(t)) return t;
715
  return WeekDay(LocalTimeNoCheck(t));
716
}
717

    
718

    
719
// ECMA 262 - 15.9.5.17
720
function DateGetUTCDay() {
721
  var t = GetTimeFrom(this);
722
  if ($isNaN(t)) return t;
723
  return WeekDay(t);
724
}
725

    
726

    
727
// ECMA 262 - 15.9.5.18
728
function DateGetHours() {
729
  return GetHoursFrom(this);
730
}
731

    
732

    
733
// ECMA 262 - 15.9.5.19
734
function DateGetUTCHours() {
735
  return GetUTCHoursFrom(this);
736
}
737

    
738

    
739
// ECMA 262 - 15.9.5.20
740
function DateGetMinutes() {
741
  return GetMinutesFrom(this);
742
}
743

    
744

    
745
// ECMA 262 - 15.9.5.21
746
function DateGetUTCMinutes() {
747
  return GetUTCMinutesFrom(this);
748
}
749

    
750

    
751
// ECMA 262 - 15.9.5.22
752
function DateGetSeconds() {
753
  return GetSecondsFrom(this);
754
}
755

    
756

    
757
// ECMA 262 - 15.9.5.23
758
function DateGetUTCSeconds() {
759
  return GetUTCSecondsFrom(this);
760
}
761

    
762

    
763
// ECMA 262 - 15.9.5.24
764
function DateGetMilliseconds() {
765
  return GetMillisecondsFrom(this);
766
}
767

    
768

    
769
// ECMA 262 - 15.9.5.25
770
function DateGetUTCMilliseconds() {
771
  return GetUTCMillisecondsFrom(this);
772
}
773

    
774

    
775
// ECMA 262 - 15.9.5.26
776
function DateGetTimezoneOffset() {
777
  var t = GetTimeFrom(this);
778
  if ($isNaN(t)) return t;
779
  return (t - LocalTimeNoCheck(t)) / msPerMinute;
780
}
781

    
782

    
783
// ECMA 262 - 15.9.5.27
784
function DateSetTime(ms) {
785
  if (!IS_DATE(this)) throw new $TypeError('this is not a Date object.');
786
  return %_SetValueOf(this, TimeClip(ToNumber(ms)));
787
}
788

    
789

    
790
// ECMA 262 - 15.9.5.28
791
function DateSetMilliseconds(ms) {
792
  var t = LocalTime(GetTimeFrom(this));
793
  ms = ToNumber(ms);
794
  var time = MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms);
795
  return %_SetValueOf(this, TimeClip(UTC(MakeDate(Day(t), time))));
796
}
797

    
798

    
799
// ECMA 262 - 15.9.5.29
800
function DateSetUTCMilliseconds(ms) {
801
  var t = GetTimeFrom(this);
802
  ms = ToNumber(ms);
803
  var time = MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms);
804
  return %_SetValueOf(this, TimeClip(MakeDate(Day(t), time)));
805
}
806

    
807

    
808
// ECMA 262 - 15.9.5.30
809
function DateSetSeconds(sec, ms) {
810
  var t = LocalTime(GetTimeFrom(this));
811
  sec = ToNumber(sec);
812
  ms = %_ArgumentsLength() < 2 ? GetMillisecondsFrom(this) : ToNumber(ms);
813
  var time = MakeTime(HourFromTime(t), MinFromTime(t), sec, ms);
814
  return %_SetValueOf(this, TimeClip(UTC(MakeDate(Day(t), time))));
815
}
816

    
817

    
818
// ECMA 262 - 15.9.5.31
819
function DateSetUTCSeconds(sec, ms) {
820
  var t = GetTimeFrom(this);
821
  sec = ToNumber(sec);
822
  ms = %_ArgumentsLength() < 2 ? GetUTCMillisecondsFrom(this) : ToNumber(ms);
823
  var time = MakeTime(HourFromTime(t), MinFromTime(t), sec, ms);
824
  return %_SetValueOf(this, TimeClip(MakeDate(Day(t), time)));
825
}
826

    
827

    
828
// ECMA 262 - 15.9.5.33
829
function DateSetMinutes(min, sec, ms) {
830
  var t = LocalTime(GetTimeFrom(this));
831
  min = ToNumber(min);
832
  var argc = %_ArgumentsLength();
833
  sec = argc < 2 ? GetSecondsFrom(this) : ToNumber(sec);
834
  ms = argc < 3 ? GetMillisecondsFrom(this) : ToNumber(ms);
835
  var time = MakeTime(HourFromTime(t), min, sec, ms);
836
  return %_SetValueOf(this, TimeClip(UTC(MakeDate(Day(t), time))));
837
}
838

    
839

    
840
// ECMA 262 - 15.9.5.34
841
function DateSetUTCMinutes(min, sec, ms) {
842
  var t = GetTimeFrom(this);
843
  min = ToNumber(min);
844
  var argc = %_ArgumentsLength();
845
  sec = argc < 2 ? GetUTCSecondsFrom(this) : ToNumber(sec);
846
  ms = argc < 3 ? GetUTCMillisecondsFrom(this) : ToNumber(ms);
847
  var time = MakeTime(HourFromTime(t), min, sec, ms);
848
  return %_SetValueOf(this, TimeClip(MakeDate(Day(t), time)));
849
}
850

    
851

    
852
// ECMA 262 - 15.9.5.35
853
function DateSetHours(hour, min, sec, ms) {
854
  var t = LocalTime(GetTimeFrom(this));
855
  hour = ToNumber(hour);
856
  var argc = %_ArgumentsLength();
857
  min = argc < 2 ? GetMinutesFrom(this) : ToNumber(min);
858
  sec = argc < 3 ? GetSecondsFrom(this) : ToNumber(sec);
859
  ms = argc < 4 ? GetMillisecondsFrom(this) : ToNumber(ms);
860
  var time = MakeTime(hour, min, sec, ms);
861
  return %_SetValueOf(this, TimeClip(UTC(MakeDate(Day(t), time))));
862
}
863

    
864

    
865
// ECMA 262 - 15.9.5.34
866
function DateSetUTCHours(hour, min, sec, ms) {
867
  var t = GetTimeFrom(this);
868
  hour = ToNumber(hour);
869
  var argc = %_ArgumentsLength();
870
  min = argc < 2 ? GetUTCMinutesFrom(this) : ToNumber(min);
871
  sec = argc < 3 ? GetUTCSecondsFrom(this) : ToNumber(sec);
872
  ms = argc < 4 ? GetUTCMillisecondsFrom(this) : ToNumber(ms);
873
  var time = MakeTime(hour, min, sec, ms);
874
  return %_SetValueOf(this, TimeClip(MakeDate(Day(t), time)));
875
}
876

    
877

    
878
// ECMA 262 - 15.9.5.36
879
function DateSetDate(date) {
880
  var t = LocalTime(GetTimeFrom(this));
881
  date = ToNumber(date);
882
  var day = MakeDay(YearFromTime(t), MonthFromTime(t), date);
883
  return %_SetValueOf(this, TimeClip(UTC(MakeDate(day, TimeWithinDay(t)))));
884
}
885

    
886

    
887
// ECMA 262 - 15.9.5.37
888
function DateSetUTCDate(date) {
889
  var t = GetTimeFrom(this);
890
  date = ToNumber(date);
891
  var day = MakeDay(YearFromTime(t), MonthFromTime(t), date);
892
  return %_SetValueOf(this, TimeClip(MakeDate(day, TimeWithinDay(t))));
893
}
894

    
895

    
896
// ECMA 262 - 15.9.5.38
897
function DateSetMonth(month, date) {
898
  var t = LocalTime(GetTimeFrom(this));
899
  month = ToNumber(month);
900
  date = %_ArgumentsLength() < 2 ? GetDateFrom(this) : ToNumber(date);
901
  var day = MakeDay(YearFromTime(t), month, date);
902
  return %_SetValueOf(this, TimeClip(UTC(MakeDate(day, TimeWithinDay(t)))));
903
}
904

    
905

    
906
// ECMA 262 - 15.9.5.39
907
function DateSetUTCMonth(month, date) {
908
  var t = GetTimeFrom(this);
909
  month = ToNumber(month);
910
  date = %_ArgumentsLength() < 2 ? GetUTCDateFrom(this) : ToNumber(date);
911
  var day = MakeDay(YearFromTime(t), month, date);
912
  return %_SetValueOf(this, TimeClip(MakeDate(day, TimeWithinDay(t))));
913
}
914

    
915

    
916
// ECMA 262 - 15.9.5.40
917
function DateSetFullYear(year, month, date) {
918
  var t = GetTimeFrom(this);
919
  t = $isNaN(t) ? 0 : LocalTimeNoCheck(t);
920
  year = ToNumber(year);
921
  var argc = %_ArgumentsLength();
922
  month = argc < 2 ? MonthFromTime(t) : ToNumber(month);
923
  date = argc < 3 ? DateFromTime(t) : ToNumber(date);
924
  var day = MakeDay(year, month, date);
925
  return %_SetValueOf(this, TimeClip(UTC(MakeDate(day, TimeWithinDay(t)))));
926
}
927

    
928

    
929
// ECMA 262 - 15.9.5.41
930
function DateSetUTCFullYear(year, month, date) {
931
  var t = GetTimeFrom(this);
932
  if ($isNaN(t)) t = 0;
933
  var argc = %_ArgumentsLength();
934
  year = ToNumber(year);
935
  month = argc < 2 ? MonthFromTime(t) : ToNumber(month);
936
  date = argc < 3 ? DateFromTime(t) : ToNumber(date);
937
  var day = MakeDay(year, month, date);
938
  return %_SetValueOf(this, TimeClip(MakeDate(day, TimeWithinDay(t))));
939
}
940

    
941

    
942
// ECMA 262 - 15.9.5.42
943
function DateToUTCString() {
944
  var t = GetTimeFrom(this);
945
  if ($isNaN(t)) return kInvalidDate;
946
  // Return UTC string of the form: Sat, 31 Jan 1970 23:00:00 GMT
947
  return WeekDays[WeekDay(t)] + ', '
948
      + TwoDigitString(DateFromTime(t)) + ' '
949
      + Months[MonthFromTime(t)] + ' '
950
      + YearFromTime(t) + ' '
951
      + TimeString(t) + ' GMT';
952
}
953

    
954

    
955
// ECMA 262 - B.2.4
956
function DateGetYear() {
957
  var t = GetTimeFrom(this);
958
  if ($isNaN(t)) return $NaN;
959
  return YearFromTime(LocalTimeNoCheck(t)) - 1900;
960
}
961

    
962

    
963
// ECMA 262 - B.2.5
964
function DateSetYear(year) {
965
  var t = LocalTime(GetTimeFrom(this));
966
  if ($isNaN(t)) t = 0;
967
  year = ToNumber(year);
968
  if ($isNaN(year)) return %_SetValueOf(this, $NaN);
969
  year = (0 <= TO_INTEGER(year) && TO_INTEGER(year) <= 99)
970
      ? 1900 + TO_INTEGER(year) : year;
971
  var day = MakeDay(year, MonthFromTime(t), DateFromTime(t));
972
  return %_SetValueOf(this, TimeClip(UTC(MakeDate(day, TimeWithinDay(t)))));
973
}
974

    
975

    
976
// ECMA 262 - B.2.6
977
//
978
// Notice that this does not follow ECMA 262 completely.  ECMA 262
979
// says that toGMTString should be the same Function object as
980
// toUTCString.  JSC does not do this, so for compatibility we do not
981
// do that either.  Instead, we create a new function whose name
982
// property will return toGMTString.
983
function DateToGMTString() {
984
  return DateToUTCString.call(this);
985
}
986

    
987

    
988
// -------------------------------------------------------------------
989

    
990
function SetupDate() {
991
  // Setup non-enumerable properties of the Date object itself.
992
  InstallFunctions($Date, DONT_ENUM, $Array(
993
    "UTC", DateUTC,
994
    "parse", DateParse,
995
    "now", DateNow
996
  ));
997

    
998
  // Setup non-enumerable constructor property of the Date prototype object.
999
  %SetProperty($Date.prototype, "constructor", $Date, DONT_ENUM);
1000

    
1001
  // Setup non-enumerable functions of the Date prototype object and
1002
  // set their names.
1003
  InstallFunctions($Date.prototype, DONT_ENUM, $Array(
1004
    "toString", DateToString,
1005
    "toDateString", DateToDateString,
1006
    "toTimeString", DateToTimeString,
1007
    "toLocaleString", DateToLocaleString,
1008
    "toLocaleDateString", DateToLocaleDateString,
1009
    "toLocaleTimeString", DateToLocaleTimeString,
1010
    "valueOf", DateValueOf,
1011
    "getTime", DateGetTime,
1012
    "getFullYear", DateGetFullYear,
1013
    "getUTCFullYear", DateGetUTCFullYear,
1014
    "getMonth", DateGetMonth,
1015
    "getUTCMonth", DateGetUTCMonth,
1016
    "getDate", DateGetDate,
1017
    "getUTCDate", DateGetUTCDate,
1018
    "getDay", DateGetDay,
1019
    "getUTCDay", DateGetUTCDay,
1020
    "getHours", DateGetHours,
1021
    "getUTCHours", DateGetUTCHours,
1022
    "getMinutes", DateGetMinutes,
1023
    "getUTCMinutes", DateGetUTCMinutes,
1024
    "getSeconds", DateGetSeconds,
1025
    "getUTCSeconds", DateGetUTCSeconds,
1026
    "getMilliseconds", DateGetMilliseconds,
1027
    "getUTCMilliseconds", DateGetUTCMilliseconds,
1028
    "getTimezoneOffset", DateGetTimezoneOffset,
1029
    "setTime", DateSetTime,
1030
    "setMilliseconds", DateSetMilliseconds,
1031
    "setUTCMilliseconds", DateSetUTCMilliseconds,
1032
    "setSeconds", DateSetSeconds,
1033
    "setUTCSeconds", DateSetUTCSeconds,
1034
    "setMinutes", DateSetMinutes,
1035
    "setUTCMinutes", DateSetUTCMinutes,
1036
    "setHours", DateSetHours,
1037
    "setUTCHours", DateSetUTCHours,
1038
    "setDate", DateSetDate,
1039
    "setUTCDate", DateSetUTCDate,
1040
    "setMonth", DateSetMonth,
1041
    "setUTCMonth", DateSetUTCMonth,
1042
    "setFullYear", DateSetFullYear,
1043
    "setUTCFullYear", DateSetUTCFullYear,
1044
    "toGMTString", DateToGMTString,
1045
    "toUTCString", DateToUTCString,
1046
    "getYear", DateGetYear,
1047
    "setYear", DateSetYear
1048
  ));
1049
}
1050

    
1051
SetupDate();