comparison mupdf-source/thirdparty/mujs/jsdate.c @ 2:b50eed0cc0ef upstream

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