jsdate.c 20 KB

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