Coverage Report

Created: 2025-01-28 06:17

/src/mupdf/thirdparty/mujs/jsdate.c
Line
Count
Source (jump to first uncovered line)
1
#include "jsi.h"
2
3
#include <time.h>
4
5
#if defined(__unix__) || defined(__APPLE__)
6
#include <sys/time.h>
7
#elif defined(_WIN32)
8
#include <sys/timeb.h>
9
#endif
10
11
0
#define js_optnumber(J,I,V) (js_isdefined(J,I) ? js_tonumber(J,I) : V)
12
13
static double Now(void)
14
0
{
15
0
#if defined(__unix__) || defined(__APPLE__)
16
0
  struct timeval tv;
17
0
  gettimeofday(&tv, NULL);
18
0
  return floor(tv.tv_sec * 1000.0 + tv.tv_usec / 1000.0);
19
#elif defined(_WIN32)
20
  struct _timeb tv;
21
  _ftime(&tv);
22
  return tv.time * 1000.0 + tv.millitm;
23
#else
24
  return time(NULL) * 1000.0;
25
#endif
26
0
}
27
28
static double LocalTZA(void)
29
0
{
30
0
  static int once = 1;
31
0
  static double tza = 0;
32
0
  if (once) {
33
0
    time_t now = time(NULL);
34
0
    time_t utc = mktime(gmtime(&now));
35
0
    time_t loc = mktime(localtime(&now));
36
0
    tza = (loc - utc) * 1000;
37
0
    once = 0;
38
0
  }
39
0
  return tza;
40
0
}
41
42
static double DaylightSavingTA(double t)
43
0
{
44
0
  return 0; /* TODO */
45
0
}
46
47
/* Helpers from the ECMA 262 specification */
48
49
0
#define HoursPerDay   24.0
50
0
#define MinutesPerDay   (HoursPerDay * MinutesPerHour)
51
0
#define MinutesPerHour    60.0
52
0
#define SecondsPerDay   (MinutesPerDay * SecondsPerMinute)
53
0
#define SecondsPerHour    (MinutesPerHour * SecondsPerMinute)
54
0
#define SecondsPerMinute  60.0
55
56
0
#define msPerDay  (SecondsPerDay * msPerSecond)
57
0
#define msPerHour (SecondsPerHour * msPerSecond)
58
0
#define msPerMinute (SecondsPerMinute * msPerSecond)
59
0
#define msPerSecond 1000.0
60
61
static double pmod(double x, double y)
62
0
{
63
0
  x = fmod(x, y);
64
0
  if (x < 0)
65
0
    x += y;
66
0
  return x;
67
0
}
68
69
static int Day(double t)
70
0
{
71
0
  return floor(t / msPerDay);
72
0
}
73
74
static double TimeWithinDay(double t)
75
0
{
76
0
  return pmod(t, msPerDay);
77
0
}
78
79
static int DaysInYear(int y)
80
0
{
81
0
  return y % 4 == 0 && (y % 100 || (y % 400 == 0)) ? 366 : 365;
82
0
}
83
84
static int DayFromYear(int y)
85
0
{
86
0
  return 365 * (y - 1970) +
87
0
    floor((y - 1969) / 4.0) -
88
0
    floor((y - 1901) / 100.0) +
89
0
    floor((y - 1601) / 400.0);
90
0
}
91
92
static double TimeFromYear(int y)
93
0
{
94
0
  return DayFromYear(y) * msPerDay;
95
0
}
96
97
static int YearFromTime(double t)
98
0
{
99
0
  int y = floor(t / (msPerDay * 365.2425)) + 1970;
100
0
  double t2 = TimeFromYear(y);
101
0
  if (t2 > t)
102
0
    --y;
103
0
  else if (t2 + msPerDay * DaysInYear(y) <= t)
104
0
    ++y;
105
0
  return y;
106
0
}
107
108
static int InLeapYear(double t)
109
0
{
110
0
  return DaysInYear(YearFromTime(t)) == 366;
111
0
}
112
113
static int DayWithinYear(double t)
114
0
{
115
0
  return Day(t) - DayFromYear(YearFromTime(t));
116
0
}
117
118
static int MonthFromTime(double t)
119
0
{
120
0
  int day = DayWithinYear(t);
121
0
  int leap = InLeapYear(t);
122
0
  if (day < 31) return 0;
123
0
  if (day < 59 + leap) return 1;
124
0
  if (day < 90 + leap) return 2;
125
0
  if (day < 120 + leap) return 3;
126
0
  if (day < 151 + leap) return 4;
127
0
  if (day < 181 + leap) return 5;
128
0
  if (day < 212 + leap) return 6;
129
0
  if (day < 243 + leap) return 7;
130
0
  if (day < 273 + leap) return 8;
131
0
  if (day < 304 + leap) return 9;
132
0
  if (day < 334 + leap) return 10;
133
0
  return 11;
134
0
}
135
136
static int DateFromTime(double t)
137
0
{
138
0
  int day = DayWithinYear(t);
139
0
  int leap = InLeapYear(t);
140
0
  switch (MonthFromTime(t)) {
141
0
  case 0: return day + 1;
142
0
  case 1: return day - 30;
143
0
  case 2: return day - 58 - leap;
144
0
  case 3: return day - 89 - leap;
145
0
  case 4: return day - 119 - leap;
146
0
  case 5: return day - 150 - leap;
147
0
  case 6: return day - 180 - leap;
148
0
  case 7: return day - 211 - leap;
149
0
  case 8: return day - 242 - leap;
150
0
  case 9: return day - 272 - leap;
151
0
  case 10: return day - 303 - leap;
152
0
  default : return day - 333 - leap;
153
0
  }
154
0
}
155
156
static int WeekDay(double t)
157
0
{
158
0
  return pmod(Day(t) + 4, 7);
159
0
}
160
161
static double LocalTime(double utc)
162
0
{
163
0
  return utc + LocalTZA() + DaylightSavingTA(utc);
164
0
}
165
166
static double UTC(double loc)
167
0
{
168
0
  return loc - LocalTZA() - DaylightSavingTA(loc - LocalTZA());
169
0
}
170
171
static int HourFromTime(double t)
172
0
{
173
0
  return pmod(floor(t / msPerHour), HoursPerDay);
174
0
}
175
176
static int MinFromTime(double t)
177
0
{
178
0
  return pmod(floor(t / msPerMinute), MinutesPerHour);
179
0
}
180
181
static int SecFromTime(double t)
182
0
{
183
0
  return pmod(floor(t / msPerSecond), SecondsPerMinute);
184
0
}
185
186
static int msFromTime(double t)
187
0
{
188
0
  return pmod(t, msPerSecond);
189
0
}
190
191
static double MakeTime(double hour, double min, double sec, double ms)
192
0
{
193
0
  return ((hour * MinutesPerHour + min) * SecondsPerMinute + sec) * msPerSecond + ms;
194
0
}
195
196
static double MakeDay(double y, double m, double date)
197
0
{
198
  /*
199
   * The following array contains the day of year for the first day of
200
   * each month, where index 0 is January, and day 0 is January 1.
201
   */
202
0
  static const double firstDayOfMonth[2][12] = {
203
0
    {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
204
0
    {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
205
0
  };
206
207
0
  double yd, md;
208
0
  int im;
209
210
0
  y += floor(m / 12);
211
0
  m = pmod(m, 12);
212
213
0
  im = (int)m;
214
0
  if (im < 0 || im >= 12)
215
0
    return NAN;
216
217
0
  yd = floor(TimeFromYear(y) / msPerDay);
218
0
  md = firstDayOfMonth[DaysInYear(y) == 366][im];
219
220
0
  return yd + md + date - 1;
221
0
}
222
223
static double MakeDate(double day, double time)
224
0
{
225
0
  return day * msPerDay + time;
226
0
}
227
228
static double TimeClip(double t)
229
0
{
230
0
  if (!isfinite(t))
231
0
    return NAN;
232
0
  if (fabs(t) > 8.64e15)
233
0
    return NAN;
234
0
  return t < 0 ? -floor(-t) : floor(t);
235
0
}
236
237
static int toint(const char **sp, int w, int *v)
238
0
{
239
0
  const char *s = *sp;
240
0
  *v = 0;
241
0
  while (w--) {
242
0
    if (*s < '0' || *s > '9')
243
0
      return 0;
244
0
    *v = *v * 10 + (*s++ - '0');
245
0
  }
246
0
  *sp = s;
247
0
  return 1;
248
0
}
249
250
static double parseDateTime(const char *s)
251
0
{
252
0
  int y = 1970, m = 1, d = 1, H = 0, M = 0, S = 0, ms = 0;
253
0
  int tza = 0;
254
0
  double t;
255
256
  /* Parse ISO 8601 formatted date and time: */
257
  /* YYYY("-"MM("-"DD)?)?("T"HH":"mm(":"ss("."sss)?)?("Z"|[+-]HH(":"mm)?)?)? */
258
259
0
  if (!toint(&s, 4, &y)) return NAN;
260
0
  if (*s == '-') {
261
0
    s += 1;
262
0
    if (!toint(&s, 2, &m)) return NAN;
263
0
    if (*s == '-') {
264
0
      s += 1;
265
0
      if (!toint(&s, 2, &d)) return NAN;
266
0
    }
267
0
  }
268
269
0
  if (*s == 'T') {
270
0
    s += 1;
271
0
    if (!toint(&s, 2, &H)) return NAN;
272
0
    if (*s != ':') return NAN;
273
0
    s += 1;
274
0
    if (!toint(&s, 2, &M)) return NAN;
275
0
    if (*s == ':') {
276
0
      s += 1;
277
0
      if (!toint(&s, 2, &S)) return NAN;
278
0
      if (*s == '.') {
279
0
        s += 1;
280
0
        if (!toint(&s, 3, &ms)) return NAN;
281
0
      }
282
0
    }
283
0
    if (*s == 'Z') {
284
0
      s += 1;
285
0
      tza = 0;
286
0
    } else if (*s == '+' || *s == '-') {
287
0
      int tzh = 0, tzm = 0;
288
0
      int tzs = *s == '+' ? 1 : -1;
289
0
      s += 1;
290
0
      if (!toint(&s, 2, &tzh)) return NAN;
291
0
      if (*s == ':') {
292
0
        s += 1;
293
0
        if (!toint(&s, 2, &tzm)) return NAN;
294
0
      }
295
0
      if (tzh > 23 || tzm > 59) return NAN;
296
0
      tza = tzs * (tzh * msPerHour + tzm * msPerMinute);
297
0
    } else {
298
0
      tza = LocalTZA();
299
0
    }
300
0
  }
301
302
0
  if (*s) return NAN;
303
304
0
  if (m < 1 || m > 12) return NAN;
305
0
  if (d < 1 || d > 31) return NAN;
306
0
  if (H < 0 || H > 24) return NAN;
307
0
  if (M < 0 || M > 59) return NAN;
308
0
  if (S < 0 || S > 59) return NAN;
309
0
  if (ms < 0 || ms > 999) return NAN;
310
0
  if (H == 24 && (M != 0 || S != 0 || ms != 0)) return NAN;
311
312
  /* TODO: DaylightSavingTA on local times */
313
0
  t = MakeDate(MakeDay(y, m-1, d), MakeTime(H, M, S, ms));
314
0
  return t - tza;
315
0
}
316
317
/* date formatting */
318
319
static char *fmtdate(char *buf, double t)
320
0
{
321
0
  int y = YearFromTime(t);
322
0
  int m = MonthFromTime(t);
323
0
  int d = DateFromTime(t);
324
0
  if (!isfinite(t))
325
0
    return "Invalid Date";
326
0
  sprintf(buf, "%04d-%02d-%02d", y, m+1, d);
327
0
  return buf;
328
0
}
329
330
static char *fmttime(char *buf, double t, double tza)
331
0
{
332
0
  int H = HourFromTime(t);
333
0
  int M = MinFromTime(t);
334
0
  int S = SecFromTime(t);
335
0
  int ms = msFromTime(t);
336
0
  int tzh = HourFromTime(fabs(tza));
337
0
  int tzm = MinFromTime(fabs(tza));
338
0
  if (!isfinite(t))
339
0
    return "Invalid Date";
340
0
  if (tza == 0)
341
0
    sprintf(buf, "%02d:%02d:%02d.%03dZ", H, M, S, ms);
342
0
  else if (tza < 0)
343
0
    sprintf(buf, "%02d:%02d:%02d.%03d-%02d:%02d", H, M, S, ms, tzh, tzm);
344
0
  else
345
0
    sprintf(buf, "%02d:%02d:%02d.%03d+%02d:%02d", H, M, S, ms, tzh, tzm);
346
0
  return buf;
347
0
}
348
349
static char *fmtdatetime(char *buf, double t, double tza)
350
0
{
351
0
  char dbuf[20], tbuf[20];
352
0
  if (!isfinite(t))
353
0
    return "Invalid Date";
354
0
  fmtdate(dbuf, t);
355
0
  fmttime(tbuf, t, tza);
356
0
  sprintf(buf, "%sT%s", dbuf, tbuf);
357
0
  return buf;
358
0
}
359
360
/* Date functions */
361
362
static double js_todate(js_State *J, int idx)
363
0
{
364
0
  js_Object *self = js_toobject(J, idx);
365
0
  if (self->type != JS_CDATE)
366
0
    js_typeerror(J, "not a date");
367
0
  return self->u.number;
368
0
}
369
370
static void js_setdate(js_State *J, int idx, double t)
371
0
{
372
0
  js_Object *self = js_toobject(J, idx);
373
0
  if (self->type != JS_CDATE)
374
0
    js_typeerror(J, "not a date");
375
0
  self->u.number = TimeClip(t);
376
0
  js_pushnumber(J, self->u.number);
377
0
}
378
379
static void D_parse(js_State *J)
380
0
{
381
0
  double t = parseDateTime(js_tostring(J, 1));
382
0
  js_pushnumber(J, t);
383
0
}
384
385
static void D_UTC(js_State *J)
386
0
{
387
0
  double y, m, d, H, M, S, ms, t;
388
0
  y = js_tonumber(J, 1);
389
0
  if (y < 100) y += 1900;
390
0
  m = js_tonumber(J, 2);
391
0
  d = js_optnumber(J, 3, 1);
392
0
  H = js_optnumber(J, 4, 0);
393
0
  M = js_optnumber(J, 5, 0);
394
0
  S = js_optnumber(J, 6, 0);
395
0
  ms = js_optnumber(J, 7, 0);
396
0
  t = MakeDate(MakeDay(y, m, d), MakeTime(H, M, S, ms));
397
0
  t = TimeClip(t);
398
0
  js_pushnumber(J, t);
399
0
}
400
401
static void D_now(js_State *J)
402
0
{
403
0
  js_pushnumber(J, Now());
404
0
}
405
406
static void jsB_Date(js_State *J)
407
0
{
408
0
  char buf[64];
409
0
  js_pushstring(J, fmtdatetime(buf, LocalTime(Now()), LocalTZA()));
410
0
}
411
412
static void jsB_new_Date(js_State *J)
413
0
{
414
0
  int top = js_gettop(J);
415
0
  js_Object *obj;
416
0
  double t;
417
418
0
  if (top == 1)
419
0
    t = Now();
420
0
  else if (top == 2) {
421
0
    js_toprimitive(J, 1, JS_HNONE);
422
0
    if (js_isstring(J, 1))
423
0
      t = parseDateTime(js_tostring(J, 1));
424
0
    else
425
0
      t = TimeClip(js_tonumber(J, 1));
426
0
  } else {
427
0
    double y, m, d, H, M, S, ms;
428
0
    y = js_tonumber(J, 1);
429
0
    if (y < 100) y += 1900;
430
0
    m = js_tonumber(J, 2);
431
0
    d = js_optnumber(J, 3, 1);
432
0
    H = js_optnumber(J, 4, 0);
433
0
    M = js_optnumber(J, 5, 0);
434
0
    S = js_optnumber(J, 6, 0);
435
0
    ms = js_optnumber(J, 7, 0);
436
0
    t = MakeDate(MakeDay(y, m, d), MakeTime(H, M, S, ms));
437
0
    t = TimeClip(UTC(t));
438
0
  }
439
440
0
  obj = jsV_newobject(J, JS_CDATE, J->Date_prototype);
441
0
  obj->u.number = t;
442
443
0
  js_pushobject(J, obj);
444
0
}
445
446
static void Dp_valueOf(js_State *J)
447
0
{
448
0
  double t = js_todate(J, 0);
449
0
  js_pushnumber(J, t);
450
0
}
451
452
static void Dp_toString(js_State *J)
453
0
{
454
0
  char buf[64];
455
0
  double t = js_todate(J, 0);
456
0
  js_pushstring(J, fmtdatetime(buf, LocalTime(t), LocalTZA()));
457
0
}
458
459
static void Dp_toDateString(js_State *J)
460
0
{
461
0
  char buf[64];
462
0
  double t = js_todate(J, 0);
463
0
  js_pushstring(J, fmtdate(buf, LocalTime(t)));
464
0
}
465
466
static void Dp_toTimeString(js_State *J)
467
0
{
468
0
  char buf[64];
469
0
  double t = js_todate(J, 0);
470
0
  js_pushstring(J, fmttime(buf, LocalTime(t), LocalTZA()));
471
0
}
472
473
static void Dp_toUTCString(js_State *J)
474
0
{
475
0
  char buf[64];
476
0
  double t = js_todate(J, 0);
477
0
  js_pushstring(J, fmtdatetime(buf, t, 0));
478
0
}
479
480
static void Dp_toISOString(js_State *J)
481
0
{
482
0
  char buf[64];
483
0
  double t = js_todate(J, 0);
484
0
  if (!isfinite(t))
485
0
    js_rangeerror(J, "invalid date");
486
0
  js_pushstring(J, fmtdatetime(buf, t, 0));
487
0
}
488
489
static void Dp_getFullYear(js_State *J)
490
0
{
491
0
  double t = js_todate(J, 0);
492
0
  if (isnan(t))
493
0
    js_pushnumber(J, NAN);
494
0
  else
495
0
    js_pushnumber(J, YearFromTime(LocalTime(t)));
496
0
}
497
498
static void Dp_getMonth(js_State *J)
499
0
{
500
0
  double t = js_todate(J, 0);
501
0
  if (isnan(t))
502
0
    js_pushnumber(J, NAN);
503
0
  else
504
0
    js_pushnumber(J, MonthFromTime(LocalTime(t)));
505
0
}
506
507
static void Dp_getDate(js_State *J)
508
0
{
509
0
  double t = js_todate(J, 0);
510
0
  if (isnan(t))
511
0
    js_pushnumber(J, NAN);
512
0
  else
513
0
    js_pushnumber(J, DateFromTime(LocalTime(t)));
514
0
}
515
516
static void Dp_getDay(js_State *J)
517
0
{
518
0
  double t = js_todate(J, 0);
519
0
  if (isnan(t))
520
0
    js_pushnumber(J, NAN);
521
0
  else
522
0
    js_pushnumber(J, WeekDay(LocalTime(t)));
523
0
}
524
525
static void Dp_getHours(js_State *J)
526
0
{
527
0
  double t = js_todate(J, 0);
528
0
  if (isnan(t))
529
0
    js_pushnumber(J, NAN);
530
0
  else
531
0
    js_pushnumber(J, HourFromTime(LocalTime(t)));
532
0
}
533
534
static void Dp_getMinutes(js_State *J)
535
0
{
536
0
  double t = js_todate(J, 0);
537
0
  if (isnan(t))
538
0
    js_pushnumber(J, NAN);
539
0
  else
540
0
    js_pushnumber(J, MinFromTime(LocalTime(t)));
541
0
}
542
543
static void Dp_getSeconds(js_State *J)
544
0
{
545
0
  double t = js_todate(J, 0);
546
0
  if (isnan(t))
547
0
    js_pushnumber(J, NAN);
548
0
  else
549
0
    js_pushnumber(J, SecFromTime(LocalTime(t)));
550
0
}
551
552
static void Dp_getMilliseconds(js_State *J)
553
0
{
554
0
  double t = js_todate(J, 0);
555
0
  if (isnan(t))
556
0
    js_pushnumber(J, NAN);
557
0
  else
558
0
    js_pushnumber(J, msFromTime(LocalTime(t)));
559
0
}
560
561
static void Dp_getUTCFullYear(js_State *J)
562
0
{
563
0
  double t = js_todate(J, 0);
564
0
  if (isnan(t))
565
0
    js_pushnumber(J, NAN);
566
0
  else
567
0
    js_pushnumber(J, YearFromTime(t));
568
0
}
569
570
static void Dp_getUTCMonth(js_State *J)
571
0
{
572
0
  double t = js_todate(J, 0);
573
0
  if (isnan(t))
574
0
    js_pushnumber(J, NAN);
575
0
  else
576
0
    js_pushnumber(J, MonthFromTime(t));
577
0
}
578
579
static void Dp_getUTCDate(js_State *J)
580
0
{
581
0
  double t = js_todate(J, 0);
582
0
  if (isnan(t))
583
0
    js_pushnumber(J, NAN);
584
0
  else
585
0
    js_pushnumber(J, DateFromTime(t));
586
0
}
587
588
static void Dp_getUTCDay(js_State *J)
589
0
{
590
0
  double t = js_todate(J, 0);
591
0
  if (isnan(t))
592
0
    js_pushnumber(J, NAN);
593
0
  else
594
0
    js_pushnumber(J, WeekDay(t));
595
0
}
596
597
static void Dp_getUTCHours(js_State *J)
598
0
{
599
0
  double t = js_todate(J, 0);
600
0
  if (isnan(t))
601
0
    js_pushnumber(J, NAN);
602
0
  else
603
0
    js_pushnumber(J, HourFromTime(t));
604
0
}
605
606
static void Dp_getUTCMinutes(js_State *J)
607
0
{
608
0
  double t = js_todate(J, 0);
609
0
  if (isnan(t))
610
0
    js_pushnumber(J, NAN);
611
0
  else
612
0
    js_pushnumber(J, MinFromTime(t));
613
0
}
614
615
static void Dp_getUTCSeconds(js_State *J)
616
0
{
617
0
  double t = js_todate(J, 0);
618
0
  if (isnan(t))
619
0
    js_pushnumber(J, NAN);
620
0
  else
621
0
    js_pushnumber(J, SecFromTime(t));
622
0
}
623
624
static void Dp_getUTCMilliseconds(js_State *J)
625
0
{
626
0
  double t = js_todate(J, 0);
627
0
  if (isnan(t))
628
0
    js_pushnumber(J, NAN);
629
0
  else
630
0
    js_pushnumber(J, msFromTime(t));
631
0
}
632
633
static void Dp_getTimezoneOffset(js_State *J)
634
0
{
635
0
  double t = js_todate(J, 0);
636
0
  if (isnan(t))
637
0
    js_pushnumber(J, NAN);
638
0
  else
639
0
    js_pushnumber(J, (t - LocalTime(t)) / msPerMinute);
640
0
}
641
642
static void Dp_setTime(js_State *J)
643
0
{
644
0
  js_setdate(J, 0, js_tonumber(J, 1));
645
0
}
646
647
static void Dp_setMilliseconds(js_State *J)
648
0
{
649
0
  double t = LocalTime(js_todate(J, 0));
650
0
  double h = HourFromTime(t);
651
0
  double m = MinFromTime(t);
652
0
  double s = SecFromTime(t);
653
0
  double ms = js_tonumber(J, 1);
654
0
  js_setdate(J, 0, UTC(MakeDate(Day(t), MakeTime(h, m, s, ms))));
655
0
}
656
657
static void Dp_setSeconds(js_State *J)
658
0
{
659
0
  double t = LocalTime(js_todate(J, 0));
660
0
  double h = HourFromTime(t);
661
0
  double m = MinFromTime(t);
662
0
  double s = js_tonumber(J, 1);
663
0
  double ms = js_optnumber(J, 2, msFromTime(t));
664
0
  js_setdate(J, 0, UTC(MakeDate(Day(t), MakeTime(h, m, s, ms))));
665
0
}
666
667
static void Dp_setMinutes(js_State *J)
668
0
{
669
0
  double t = LocalTime(js_todate(J, 0));
670
0
  double h = HourFromTime(t);
671
0
  double m = js_tonumber(J, 1);
672
0
  double s = js_optnumber(J, 2, SecFromTime(t));
673
0
  double ms = js_optnumber(J, 3, msFromTime(t));
674
0
  js_setdate(J, 0, UTC(MakeDate(Day(t), MakeTime(h, m, s, ms))));
675
0
}
676
677
static void Dp_setHours(js_State *J)
678
0
{
679
0
  double t = LocalTime(js_todate(J, 0));
680
0
  double h = js_tonumber(J, 1);
681
0
  double m = js_optnumber(J, 2, MinFromTime(t));
682
0
  double s = js_optnumber(J, 3, SecFromTime(t));
683
0
  double ms = js_optnumber(J, 4, msFromTime(t));
684
0
  js_setdate(J, 0, UTC(MakeDate(Day(t), MakeTime(h, m, s, ms))));
685
0
}
686
687
static void Dp_setDate(js_State *J)
688
0
{
689
0
  double t = LocalTime(js_todate(J, 0));
690
0
  double y = YearFromTime(t);
691
0
  double m = MonthFromTime(t);
692
0
  double d = js_tonumber(J, 1);
693
0
  js_setdate(J, 0, UTC(MakeDate(MakeDay(y, m, d), TimeWithinDay(t))));
694
0
}
695
696
static void Dp_setMonth(js_State *J)
697
0
{
698
0
  double t = LocalTime(js_todate(J, 0));
699
0
  double y = YearFromTime(t);
700
0
  double m = js_tonumber(J, 1);
701
0
  double d = js_optnumber(J, 2, DateFromTime(t));
702
0
  js_setdate(J, 0, UTC(MakeDate(MakeDay(y, m, d), TimeWithinDay(t))));
703
0
}
704
705
static void Dp_setFullYear(js_State *J)
706
0
{
707
0
  double t = LocalTime(js_todate(J, 0));
708
0
  double y = js_tonumber(J, 1);
709
0
  double m = js_optnumber(J, 2, MonthFromTime(t));
710
0
  double d = js_optnumber(J, 3, DateFromTime(t));
711
0
  js_setdate(J, 0, UTC(MakeDate(MakeDay(y, m, d), TimeWithinDay(t))));
712
0
}
713
714
static void Dp_setUTCMilliseconds(js_State *J)
715
0
{
716
0
  double t = js_todate(J, 0);
717
0
  double h = HourFromTime(t);
718
0
  double m = MinFromTime(t);
719
0
  double s = SecFromTime(t);
720
0
  double ms = js_tonumber(J, 1);
721
0
  js_setdate(J, 0, MakeDate(Day(t), MakeTime(h, m, s, ms)));
722
0
}
723
724
static void Dp_setUTCSeconds(js_State *J)
725
0
{
726
0
  double t = js_todate(J, 0);
727
0
  double h = HourFromTime(t);
728
0
  double m = MinFromTime(t);
729
0
  double s = js_tonumber(J, 1);
730
0
  double ms = js_optnumber(J, 2, msFromTime(t));
731
0
  js_setdate(J, 0, MakeDate(Day(t), MakeTime(h, m, s, ms)));
732
0
}
733
734
static void Dp_setUTCMinutes(js_State *J)
735
0
{
736
0
  double t = js_todate(J, 0);
737
0
  double h = HourFromTime(t);
738
0
  double m = js_tonumber(J, 1);
739
0
  double s = js_optnumber(J, 2, SecFromTime(t));
740
0
  double ms = js_optnumber(J, 3, msFromTime(t));
741
0
  js_setdate(J, 0, MakeDate(Day(t), MakeTime(h, m, s, ms)));
742
0
}
743
744
static void Dp_setUTCHours(js_State *J)
745
0
{
746
0
  double t = js_todate(J, 0);
747
0
  double h = js_tonumber(J, 1);
748
0
  double m = js_optnumber(J, 2, HourFromTime(t));
749
0
  double s = js_optnumber(J, 3, SecFromTime(t));
750
0
  double ms = js_optnumber(J, 4, msFromTime(t));
751
0
  js_setdate(J, 0, MakeDate(Day(t), MakeTime(h, m, s, ms)));
752
0
}
753
754
static void Dp_setUTCDate(js_State *J)
755
0
{
756
0
  double t = js_todate(J, 0);
757
0
  double y = YearFromTime(t);
758
0
  double m = MonthFromTime(t);
759
0
  double d = js_tonumber(J, 1);
760
0
  js_setdate(J, 0, MakeDate(MakeDay(y, m, d), TimeWithinDay(t)));
761
0
}
762
763
static void Dp_setUTCMonth(js_State *J)
764
0
{
765
0
  double t = js_todate(J, 0);
766
0
  double y = YearFromTime(t);
767
0
  double m = js_tonumber(J, 1);
768
0
  double d = js_optnumber(J, 2, DateFromTime(t));
769
0
  js_setdate(J, 0, MakeDate(MakeDay(y, m, d), TimeWithinDay(t)));
770
0
}
771
772
static void Dp_setUTCFullYear(js_State *J)
773
0
{
774
0
  double t = js_todate(J, 0);
775
0
  double y = js_tonumber(J, 1);
776
0
  double m = js_optnumber(J, 2, MonthFromTime(t));
777
0
  double d = js_optnumber(J, 3, DateFromTime(t));
778
0
  js_setdate(J, 0, MakeDate(MakeDay(y, m, d), TimeWithinDay(t)));
779
0
}
780
781
static void Dp_toJSON(js_State *J)
782
0
{
783
0
  js_copy(J, 0);
784
0
  js_toprimitive(J, -1, JS_HNUMBER);
785
0
  if (js_isnumber(J, -1) && !isfinite(js_tonumber(J, -1))) {
786
0
    js_pushnull(J);
787
0
    return;
788
0
  }
789
0
  js_pop(J, 1);
790
791
0
  js_getproperty(J, 0, "toISOString");
792
0
  if (!js_iscallable(J, -1))
793
0
    js_typeerror(J, "this.toISOString is not a function");
794
0
  js_copy(J, 0);
795
0
  js_call(J, 0);
796
0
}
797
798
void jsB_initdate(js_State *J)
799
0
{
800
0
  J->Date_prototype->u.number = 0;
801
802
0
  js_pushobject(J, J->Date_prototype);
803
0
  {
804
0
    jsB_propf(J, "Date.prototype.valueOf", Dp_valueOf, 0);
805
0
    jsB_propf(J, "Date.prototype.toString", Dp_toString, 0);
806
0
    jsB_propf(J, "Date.prototype.toDateString", Dp_toDateString, 0);
807
0
    jsB_propf(J, "Date.prototype.toTimeString", Dp_toTimeString, 0);
808
0
    jsB_propf(J, "Date.prototype.toLocaleString", Dp_toString, 0);
809
0
    jsB_propf(J, "Date.prototype.toLocaleDateString", Dp_toDateString, 0);
810
0
    jsB_propf(J, "Date.prototype.toLocaleTimeString", Dp_toTimeString, 0);
811
0
    jsB_propf(J, "Date.prototype.toUTCString", Dp_toUTCString, 0);
812
813
0
    jsB_propf(J, "Date.prototype.getTime", Dp_valueOf, 0);
814
0
    jsB_propf(J, "Date.prototype.getFullYear", Dp_getFullYear, 0);
815
0
    jsB_propf(J, "Date.prototype.getUTCFullYear", Dp_getUTCFullYear, 0);
816
0
    jsB_propf(J, "Date.prototype.getMonth", Dp_getMonth, 0);
817
0
    jsB_propf(J, "Date.prototype.getUTCMonth", Dp_getUTCMonth, 0);
818
0
    jsB_propf(J, "Date.prototype.getDate", Dp_getDate, 0);
819
0
    jsB_propf(J, "Date.prototype.getUTCDate", Dp_getUTCDate, 0);
820
0
    jsB_propf(J, "Date.prototype.getDay", Dp_getDay, 0);
821
0
    jsB_propf(J, "Date.prototype.getUTCDay", Dp_getUTCDay, 0);
822
0
    jsB_propf(J, "Date.prototype.getHours", Dp_getHours, 0);
823
0
    jsB_propf(J, "Date.prototype.getUTCHours", Dp_getUTCHours, 0);
824
0
    jsB_propf(J, "Date.prototype.getMinutes", Dp_getMinutes, 0);
825
0
    jsB_propf(J, "Date.prototype.getUTCMinutes", Dp_getUTCMinutes, 0);
826
0
    jsB_propf(J, "Date.prototype.getSeconds", Dp_getSeconds, 0);
827
0
    jsB_propf(J, "Date.prototype.getUTCSeconds", Dp_getUTCSeconds, 0);
828
0
    jsB_propf(J, "Date.prototype.getMilliseconds", Dp_getMilliseconds, 0);
829
0
    jsB_propf(J, "Date.prototype.getUTCMilliseconds", Dp_getUTCMilliseconds, 0);
830
0
    jsB_propf(J, "Date.prototype.getTimezoneOffset", Dp_getTimezoneOffset, 0);
831
832
0
    jsB_propf(J, "Date.prototype.setTime", Dp_setTime, 1);
833
0
    jsB_propf(J, "Date.prototype.setMilliseconds", Dp_setMilliseconds, 1);
834
0
    jsB_propf(J, "Date.prototype.setUTCMilliseconds", Dp_setUTCMilliseconds, 1);
835
0
    jsB_propf(J, "Date.prototype.setSeconds", Dp_setSeconds, 2);
836
0
    jsB_propf(J, "Date.prototype.setUTCSeconds", Dp_setUTCSeconds, 2);
837
0
    jsB_propf(J, "Date.prototype.setMinutes", Dp_setMinutes, 3);
838
0
    jsB_propf(J, "Date.prototype.setUTCMinutes", Dp_setUTCMinutes, 3);
839
0
    jsB_propf(J, "Date.prototype.setHours", Dp_setHours, 4);
840
0
    jsB_propf(J, "Date.prototype.setUTCHours", Dp_setUTCHours, 4);
841
0
    jsB_propf(J, "Date.prototype.setDate", Dp_setDate, 1);
842
0
    jsB_propf(J, "Date.prototype.setUTCDate", Dp_setUTCDate, 1);
843
0
    jsB_propf(J, "Date.prototype.setMonth", Dp_setMonth, 2);
844
0
    jsB_propf(J, "Date.prototype.setUTCMonth", Dp_setUTCMonth, 2);
845
0
    jsB_propf(J, "Date.prototype.setFullYear", Dp_setFullYear, 3);
846
0
    jsB_propf(J, "Date.prototype.setUTCFullYear", Dp_setUTCFullYear, 3);
847
848
    /* ES5 */
849
0
    jsB_propf(J, "Date.prototype.toISOString", Dp_toISOString, 0);
850
0
    jsB_propf(J, "Date.prototype.toJSON", Dp_toJSON, 1);
851
0
  }
852
0
  js_newcconstructor(J, jsB_Date, jsB_new_Date, "Date", 0); /* 1 */
853
0
  {
854
0
    jsB_propf(J, "Date.parse", D_parse, 1);
855
0
    jsB_propf(J, "Date.UTC", D_UTC, 7);
856
857
    /* ES5 */
858
0
    jsB_propf(J, "Date.now", D_now, 0);
859
0
  }
860
0
  js_defglobal(J, "Date", JS_DONTENUM);
861
0
}