PageRenderTime 64ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/dll/win32/jscript/date.c

https://bitbucket.org/arty/arty-newcc-reactos
C | 2632 lines | 2026 code | 508 blank | 98 comment | 488 complexity | f9eb3a8f9a3ca66747e9f5f09c0cccc8 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, LGPL-3.0, CC-BY-SA-3.0, AGPL-3.0, GPL-3.0, CPL-1.0
  1. /*
  2. * Copyright 2008 Jacek Caban for CodeWeavers
  3. * Copyright 2009 Piotr Caban
  4. *
  5. * This library is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU Lesser General Public
  7. * License as published by the Free Software Foundation; either
  8. * version 2.1 of the License, or (at your option) any later version.
  9. *
  10. * This library is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * Lesser General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Lesser General Public
  16. * License along with this library; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  18. */
  19. #include "config.h"
  20. #include "wine/port.h"
  21. #include <limits.h>
  22. #include <math.h>
  23. #include "jscript.h"
  24. #include "wine/debug.h"
  25. WINE_DEFAULT_DEBUG_CHANNEL(jscript);
  26. /* 1601 to 1970 is 369 years plus 89 leap days */
  27. #define TIME_EPOCH ((ULONGLONG)(369 * 365 + 89) * 86400 * 1000)
  28. typedef struct {
  29. DispatchEx dispex;
  30. /* ECMA-262 3rd Edition 15.9.1.1 */
  31. DOUBLE time;
  32. LONG bias;
  33. SYSTEMTIME standardDate;
  34. LONG standardBias;
  35. SYSTEMTIME daylightDate;
  36. LONG daylightBias;
  37. } DateInstance;
  38. static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0};
  39. static const WCHAR toLocaleStringW[] = {'t','o','L','o','c','a','l','e','S','t','r','i','n','g',0};
  40. static const WCHAR propertyIsEnumerableW[] =
  41. {'p','r','o','p','e','r','t','y','I','s','E','n','u','m','e','r','a','b','l','e',0};
  42. static const WCHAR isPrototypeOfW[] = {'i','s','P','r','o','t','o','t','y','p','e','O','f',0};
  43. static const WCHAR valueOfW[] = {'v','a','l','u','e','O','f',0};
  44. static const WCHAR toUTCStringW[] = {'t','o','U','T','C','S','t','r','i','n','g',0};
  45. static const WCHAR toGMTStringW[] = {'t','o','G','M','T','S','t','r','i','n','g',0};
  46. static const WCHAR toDateStringW[] = {'t','o','D','a','t','e','S','t','r','i','n','g',0};
  47. static const WCHAR toTimeStringW[] = {'t','o','T','i','m','e','S','t','r','i','n','g',0};
  48. static const WCHAR toLocaleDateStringW[] = {'t','o','L','o','c','a','l','e','D','a','t','e','S','t','r','i','n','g',0};
  49. static const WCHAR toLocaleTimeStringW[] = {'t','o','L','o','c','a','l','e','T','i','m','e','S','t','r','i','n','g',0};
  50. static const WCHAR getTimeW[] = {'g','e','t','T','i','m','e',0};
  51. static const WCHAR getFullYearW[] = {'g','e','t','F','u','l','l','Y','e','a','r',0};
  52. static const WCHAR getUTCFullYearW[] = {'g','e','t','U','T','C','F','u','l','l','Y','e','a','r',0};
  53. static const WCHAR getMonthW[] = {'g','e','t','M','o','n','t','h',0};
  54. static const WCHAR getUTCMonthW[] = {'g','e','t','U','T','C','M','o','n','t','h',0};
  55. static const WCHAR getDateW[] = {'g','e','t','D','a','t','e',0};
  56. static const WCHAR getUTCDateW[] = {'g','e','t','U','T','C','D','a','t','e',0};
  57. static const WCHAR getDayW[] = {'g','e','t','D','a','y',0};
  58. static const WCHAR getUTCDayW[] = {'g','e','t','U','T','C','D','a','y',0};
  59. static const WCHAR getHoursW[] = {'g','e','t','H','o','u','r','s',0};
  60. static const WCHAR getUTCHoursW[] = {'g','e','t','U','T','C','H','o','u','r','s',0};
  61. static const WCHAR getMinutesW[] = {'g','e','t','M','i','n','u','t','e','s',0};
  62. static const WCHAR getUTCMinutesW[] = {'g','e','t','U','T','C','M','i','n','u','t','e','s',0};
  63. static const WCHAR getSecondsW[] = {'g','e','t','S','e','c','o','n','d','s',0};
  64. static const WCHAR getUTCSecondsW[] = {'g','e','t','U','T','C','S','e','c','o','n','d','s',0};
  65. static const WCHAR getMillisecondsW[] = {'g','e','t','M','i','l','l','i','s','e','c','o','n','d','s',0};
  66. static const WCHAR getUTCMillisecondsW[] = {'g','e','t','U','T','C','M','i','l','l','i','s','e','c','o','n','d','s',0};
  67. static const WCHAR getTimezoneOffsetW[] = {'g','e','t','T','i','m','e','z','o','n','e','O','f','f','s','e','t',0};
  68. static const WCHAR setTimeW[] = {'s','e','t','T','i','m','e',0};
  69. static const WCHAR setMillisecondsW[] = {'s','e','t','M','i','l','l','i','s','e','c','o','n','d','s',0};
  70. static const WCHAR setUTCMillisecondsW[] = {'s','e','t','U','T','C','M','i','l','l','i','s','e','c','o','n','d','s',0};
  71. static const WCHAR setSecondsW[] = {'s','e','t','S','e','c','o','n','d','s',0};
  72. static const WCHAR setUTCSecondsW[] = {'s','e','t','U','T','C','S','e','c','o','n','d','s',0};
  73. static const WCHAR setMinutesW[] = {'s','e','t','M','i','n','u','t','e','s',0};
  74. static const WCHAR setUTCMinutesW[] = {'s','e','t','U','T','C','M','i','n','u','t','e','s',0};
  75. static const WCHAR setHoursW[] = {'s','e','t','H','o','u','r','s',0};
  76. static const WCHAR setUTCHoursW[] = {'s','e','t','U','T','C','H','o','u','r','s',0};
  77. static const WCHAR setDateW[] = {'s','e','t','D','a','t','e',0};
  78. static const WCHAR setUTCDateW[] = {'s','e','t','U','T','C','D','a','t','e',0};
  79. static const WCHAR setMonthW[] = {'s','e','t','M','o','n','t','h',0};
  80. static const WCHAR setUTCMonthW[] = {'s','e','t','U','T','C','M','o','n','t','h',0};
  81. static const WCHAR setFullYearW[] = {'s','e','t','F','u','l','l','Y','e','a','r',0};
  82. static const WCHAR setUTCFullYearW[] = {'s','e','t','U','T','C','F','u','l','l','Y','e','a','r',0};
  83. static const WCHAR getYearW[] = {'g','e','t','Y','e','a','r',0};
  84. static const WCHAR UTCW[] = {'U','T','C',0};
  85. static const WCHAR parseW[] = {'p','a','r','s','e',0};
  86. static inline DateInstance *date_this(vdisp_t *jsthis)
  87. {
  88. return is_vclass(jsthis, JSCLASS_DATE) ? (DateInstance*)jsthis->u.jsdisp : NULL;
  89. }
  90. /*ECMA-262 3rd Edition 15.9.1.2 */
  91. #define MS_PER_DAY 86400000
  92. #define MS_PER_HOUR 3600000
  93. #define MS_PER_MINUTE 60000
  94. /* ECMA-262 3rd Edition 15.9.1.2 */
  95. static inline DOUBLE day(DOUBLE time)
  96. {
  97. return floor(time / MS_PER_DAY);
  98. }
  99. /* ECMA-262 3rd Edition 15.9.1.2 */
  100. static inline DOUBLE time_within_day(DOUBLE time)
  101. {
  102. DOUBLE ret;
  103. ret = fmod(time, MS_PER_DAY);
  104. if(ret < 0)
  105. ret += MS_PER_DAY;
  106. return ret;
  107. }
  108. /* ECMA-262 3rd Edition 15.9.1.3 */
  109. static inline DOUBLE days_in_year(DOUBLE year)
  110. {
  111. int y;
  112. if(year != (int)year)
  113. return ret_nan();
  114. y = year;
  115. if(y%4 != 0) return 365;
  116. if(y%100 != 0) return 366;
  117. if(y%400 != 0) return 365;
  118. return 366;
  119. }
  120. /* ECMA-262 3rd Edition 15.9.1.3 */
  121. static inline DOUBLE day_from_year(DOUBLE year)
  122. {
  123. if(year != (int)year)
  124. return ret_nan();
  125. return floor(365.0*(year-1970) + floor((year-1969)/4)
  126. - floor((year-1901)/100) + floor((year-1601)/400));
  127. }
  128. static inline int day_from_month(int month, int in_leap_year)
  129. {
  130. switch(month)
  131. {
  132. case 0:
  133. return 0;
  134. case 1:
  135. return 31;
  136. case 2:
  137. return 59+in_leap_year;
  138. case 3:
  139. return 90+in_leap_year;
  140. case 4:
  141. return 120+in_leap_year;
  142. case 5:
  143. return 151+in_leap_year;
  144. case 6:
  145. return 181+in_leap_year;
  146. case 7:
  147. return 212+in_leap_year;
  148. case 8:
  149. return 243+in_leap_year;
  150. case 9:
  151. return 273+in_leap_year;
  152. case 10:
  153. return 304+in_leap_year;
  154. default:
  155. return 334+in_leap_year;
  156. }
  157. }
  158. /* ECMA-262 3rd Edition 15.9.1.3 */
  159. static inline DOUBLE time_from_year(DOUBLE year)
  160. {
  161. return MS_PER_DAY*day_from_year(year);
  162. }
  163. /* ECMA-262 3rd Edition 15.9.1.3 */
  164. static inline DOUBLE year_from_time(DOUBLE time)
  165. {
  166. int y;
  167. if(isnan(time))
  168. return ret_nan();
  169. y = 1970 + time/365.25/MS_PER_DAY;
  170. if(time_from_year(y) > time)
  171. while(time_from_year(y) > time) y--;
  172. else
  173. while(time_from_year(y+1)<=time) y++;
  174. return y;
  175. }
  176. /* ECMA-262 3rd Edition 15.9.1.3 */
  177. static inline int in_leap_year(DOUBLE time)
  178. {
  179. if(days_in_year(year_from_time(time))==366)
  180. return 1;
  181. return 0;
  182. }
  183. /* ECMA-262 3rd Edition 15.9.1.4 */
  184. static inline int day_within_year(DOUBLE time)
  185. {
  186. return day(time) - day_from_year(year_from_time(time));
  187. }
  188. /* ECMA-262 3rd Edition 15.9.1.4 */
  189. static inline DOUBLE month_from_time(DOUBLE time)
  190. {
  191. int ily = in_leap_year(time);
  192. int dwy = day_within_year(time);
  193. if(isnan(time))
  194. return ret_nan();
  195. if(0<=dwy && dwy<31) return 0;
  196. if(dwy < 59+ily) return 1;
  197. if(dwy < 90+ily) return 2;
  198. if(dwy < 120+ily) return 3;
  199. if(dwy < 151+ily) return 4;
  200. if(dwy < 181+ily) return 5;
  201. if(dwy < 212+ily) return 6;
  202. if(dwy < 243+ily) return 7;
  203. if(dwy < 273+ily) return 8;
  204. if(dwy < 304+ily) return 9;
  205. if(dwy < 334+ily) return 10;
  206. return 11;
  207. }
  208. /* ECMA-262 3rd Edition 15.9.1.5 */
  209. static inline DOUBLE date_from_time(DOUBLE time)
  210. {
  211. int dwy = day_within_year(time);
  212. int ily = in_leap_year(time);
  213. int mft = month_from_time(time);
  214. if(isnan(time))
  215. return ret_nan();
  216. if(mft==0) return dwy+1;
  217. if(mft==1) return dwy-30;
  218. if(mft==2) return dwy-58-ily;
  219. if(mft==3) return dwy-89-ily;
  220. if(mft==4) return dwy-119-ily;
  221. if(mft==5) return dwy-150-ily;
  222. if(mft==6) return dwy-180-ily;
  223. if(mft==7) return dwy-211-ily;
  224. if(mft==8) return dwy-242-ily;
  225. if(mft==9) return dwy-272-ily;
  226. if(mft==10) return dwy-303-ily;
  227. return dwy-333-ily;
  228. }
  229. /* ECMA-262 3rd Edition 15.9.1.6 */
  230. static inline DOUBLE week_day(DOUBLE time)
  231. {
  232. DOUBLE ret;
  233. if(isnan(time))
  234. return ret_nan();
  235. ret = fmod(day(time)+4, 7);
  236. if(ret<0) ret += 7;
  237. return ret;
  238. }
  239. static inline DOUBLE convert_time(int year, SYSTEMTIME st)
  240. {
  241. DOUBLE time;
  242. int set_week_day;
  243. if(st.wMonth == 0)
  244. return ret_nan();
  245. if(st.wYear != 0)
  246. year = st.wYear;
  247. time = time_from_year(year);
  248. time += (DOUBLE)day_from_month(st.wMonth-1, in_leap_year(time)) * MS_PER_DAY;
  249. if(st.wYear == 0) {
  250. set_week_day = st.wDayOfWeek-week_day(time);
  251. if(set_week_day < 0)
  252. set_week_day += 7;
  253. time += set_week_day * MS_PER_DAY;
  254. time += (DOUBLE)(st.wDay-1) * 7 * MS_PER_DAY;
  255. if(month_from_time(time) != st.wMonth-1)
  256. time -= 7 * MS_PER_DAY;
  257. }
  258. else
  259. time += st.wDay * MS_PER_DAY;
  260. time += st.wHour * MS_PER_HOUR;
  261. time += st.wMinute * MS_PER_MINUTE;
  262. return time;
  263. }
  264. /* ECMA-262 3rd Edition 15.9.1.9 */
  265. static inline DOUBLE daylight_saving_ta(DOUBLE time, DateInstance *date)
  266. {
  267. int year = year_from_time(time);
  268. DOUBLE standardTime, daylightTime;
  269. if(isnan(time))
  270. return 0;
  271. standardTime = convert_time(year, date->standardDate);
  272. daylightTime = convert_time(year, date->daylightDate);
  273. if(isnan(standardTime) || isnan(daylightTime))
  274. return 0;
  275. else if(standardTime > daylightTime) {
  276. if(daylightTime <= time && time < standardTime)
  277. return date->daylightBias;
  278. return date->standardBias;
  279. }
  280. else {
  281. if(standardTime <= time && time < daylightTime)
  282. return date->standardBias;
  283. return date->daylightBias;
  284. }
  285. }
  286. /* ECMA-262 3rd Edition 15.9.1.9 */
  287. static inline DOUBLE local_time(DOUBLE time, DateInstance *date)
  288. {
  289. return time - (daylight_saving_ta(time, date)+date->bias)*MS_PER_MINUTE;
  290. }
  291. /* ECMA-262 3rd Edition 15.9.1.9 */
  292. static inline DOUBLE utc(DOUBLE time, DateInstance *date)
  293. {
  294. time += date->bias * MS_PER_MINUTE;
  295. return time + daylight_saving_ta(time, date)*MS_PER_MINUTE;
  296. }
  297. /* ECMA-262 3rd Edition 15.9.1.10 */
  298. static inline DOUBLE hour_from_time(DOUBLE time)
  299. {
  300. DOUBLE ret;
  301. if(isnan(time))
  302. return ret_nan();
  303. ret = fmod(floor(time/MS_PER_HOUR), 24);
  304. if(ret<0) ret += 24;
  305. return ret;
  306. }
  307. /* ECMA-262 3rd Edition 15.9.1.10 */
  308. static inline DOUBLE min_from_time(DOUBLE time)
  309. {
  310. DOUBLE ret;
  311. if(isnan(time))
  312. return ret_nan();
  313. ret = fmod(floor(time/MS_PER_MINUTE), 60);
  314. if(ret<0) ret += 60;
  315. return ret;
  316. }
  317. /* ECMA-262 3rd Edition 15.9.1.10 */
  318. static inline DOUBLE sec_from_time(DOUBLE time)
  319. {
  320. DOUBLE ret;
  321. if(isnan(time))
  322. return ret_nan();
  323. ret = fmod(floor(time/1000), 60);
  324. if(ret<0) ret += 60;
  325. return ret;
  326. }
  327. /* ECMA-262 3rd Edition 15.9.1.10 */
  328. static inline DOUBLE ms_from_time(DOUBLE time)
  329. {
  330. DOUBLE ret;
  331. if(isnan(time))
  332. return ret_nan();
  333. ret = fmod(time, 1000);
  334. if(ret<0) ret += 1000;
  335. return ret;
  336. }
  337. /* ECMA-262 3rd Edition 15.9.1.11 */
  338. static inline DOUBLE make_time(DOUBLE hour, DOUBLE min, DOUBLE sec, DOUBLE ms)
  339. {
  340. return hour*MS_PER_HOUR + min*MS_PER_MINUTE + sec*1000 + ms;
  341. }
  342. /* ECMA-262 3rd Edition 15.9.1.12 */
  343. static inline DOUBLE make_day(DOUBLE year, DOUBLE month, DOUBLE day)
  344. {
  345. DOUBLE time;
  346. year += floor(month/12);
  347. month = fmod(month, 12);
  348. if(month<0) month += 12;
  349. time = time_from_year(year);
  350. day += floor(time / MS_PER_DAY);
  351. day += day_from_month(month, in_leap_year(time));
  352. return day-1;
  353. }
  354. /* ECMA-262 3rd Edition 15.9.1.13 */
  355. static inline DOUBLE make_date(DOUBLE day, DOUBLE time)
  356. {
  357. return day*MS_PER_DAY + time;
  358. }
  359. /* ECMA-262 3rd Edition 15.9.1.14 */
  360. static inline DOUBLE time_clip(DOUBLE time)
  361. {
  362. if(8.64e15 < time || time < -8.64e15) {
  363. return ret_nan();
  364. }
  365. return floor(time);
  366. }
  367. static SYSTEMTIME create_systemtime(DOUBLE time)
  368. {
  369. SYSTEMTIME st;
  370. st.wYear = year_from_time(time);
  371. st.wMonth = month_from_time(time) + 1;
  372. st.wDayOfWeek = week_day(time);
  373. st.wDay = date_from_time(time);
  374. st.wHour = hour_from_time(time);
  375. st.wMinute = min_from_time(time);
  376. st.wSecond = sec_from_time(time);
  377. st.wMilliseconds = ms_from_time(time);
  378. return st;
  379. }
  380. static inline HRESULT date_to_string(DOUBLE time, BOOL show_offset, int offset, VARIANT *retv)
  381. {
  382. static const WCHAR NaNW[] = { 'N','a','N',0 };
  383. static const WCHAR formatW[] = { '%','s',' ','%','s',' ','%','d',' ',
  384. '%','0','2','d',':','%','0','2','d',':','%','0','2','d',' ',
  385. 'U','T','C','%','c','%','0','2','d','%','0','2','d',' ','%','d','%','s',0 };
  386. static const WCHAR formatUTCW[] = { '%','s',' ','%','s',' ','%','d',' ',
  387. '%','0','2','d',':','%','0','2','d',':','%','0','2','d',' ',
  388. 'U','T','C',' ','%','d','%','s',0 };
  389. static const WCHAR formatNoOffsetW[] = { '%','s',' ','%','s',' ',
  390. '%','d',' ','%','0','2','d',':','%','0','2','d',':',
  391. '%','0','2','d',' ','%','d','%','s',0 };
  392. static const WCHAR ADW[] = { 0 };
  393. static const WCHAR BCW[] = { ' ','B','.','C','.',0 };
  394. static const DWORD week_ids[] = { LOCALE_SABBREVDAYNAME7, LOCALE_SABBREVDAYNAME1,
  395. LOCALE_SABBREVDAYNAME2, LOCALE_SABBREVDAYNAME3, LOCALE_SABBREVDAYNAME4,
  396. LOCALE_SABBREVDAYNAME5, LOCALE_SABBREVDAYNAME6 };
  397. static const DWORD month_ids[] = { LOCALE_SABBREVMONTHNAME1, LOCALE_SABBREVMONTHNAME2,
  398. LOCALE_SABBREVMONTHNAME3, LOCALE_SABBREVMONTHNAME4,
  399. LOCALE_SABBREVMONTHNAME5, LOCALE_SABBREVMONTHNAME6,
  400. LOCALE_SABBREVMONTHNAME7, LOCALE_SABBREVMONTHNAME8,
  401. LOCALE_SABBREVMONTHNAME9, LOCALE_SABBREVMONTHNAME10,
  402. LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12 };
  403. BOOL formatAD = TRUE;
  404. BSTR week, month;
  405. BSTR date_str;
  406. int len, size, year, day;
  407. DWORD lcid_en, week_id, month_id;
  408. WCHAR sign = '-';
  409. if(isnan(time)) {
  410. if(retv) {
  411. V_VT(retv) = VT_BSTR;
  412. V_BSTR(retv) = SysAllocString(NaNW);
  413. if(!V_BSTR(retv))
  414. return E_OUTOFMEMORY;
  415. }
  416. return S_OK;
  417. }
  418. if(retv) {
  419. len = 21;
  420. lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT);
  421. week_id = week_ids[(int)week_day(time)];
  422. size = GetLocaleInfoW(lcid_en, week_id, NULL, 0);
  423. week = SysAllocStringLen(NULL, size);
  424. if(!week)
  425. return E_OUTOFMEMORY;
  426. GetLocaleInfoW(lcid_en, week_id, week, size);
  427. len += size-1;
  428. month_id = month_ids[(int)month_from_time(time)];
  429. size = GetLocaleInfoW(lcid_en, month_id, NULL, 0);
  430. month = SysAllocStringLen(NULL, size);
  431. if(!month) {
  432. SysFreeString(week);
  433. return E_OUTOFMEMORY;
  434. }
  435. GetLocaleInfoW(lcid_en, month_id, month, size);
  436. len += size-1;
  437. year = year_from_time(time);
  438. if(year<0)
  439. year = -year+1;
  440. do {
  441. year /= 10;
  442. len++;
  443. } while(year);
  444. year = year_from_time(time);
  445. if(year<0) {
  446. formatAD = FALSE;
  447. year = -year+1;
  448. len += 5;
  449. }
  450. day = date_from_time(time);
  451. do {
  452. day /= 10;
  453. len++;
  454. } while(day);
  455. day = date_from_time(time);
  456. if(!show_offset) len -= 9;
  457. else if(offset == 0) len -= 5;
  458. else if(offset < 0) {
  459. sign = '+';
  460. offset = -offset;
  461. }
  462. date_str = SysAllocStringLen(NULL, len);
  463. if(!date_str) {
  464. SysFreeString(week);
  465. SysFreeString(month);
  466. return E_OUTOFMEMORY;
  467. }
  468. if(!show_offset)
  469. sprintfW(date_str, formatNoOffsetW, week, month, day,
  470. (int)hour_from_time(time), (int)min_from_time(time),
  471. (int)sec_from_time(time), year, formatAD?ADW:BCW);
  472. else if(offset)
  473. sprintfW(date_str, formatW, week, month, day,
  474. (int)hour_from_time(time), (int)min_from_time(time),
  475. (int)sec_from_time(time), sign, offset/60, offset%60,
  476. year, formatAD?ADW:BCW);
  477. else
  478. sprintfW(date_str, formatUTCW, week, month, day,
  479. (int)hour_from_time(time), (int)min_from_time(time),
  480. (int)sec_from_time(time), year, formatAD?ADW:BCW);
  481. SysFreeString(week);
  482. SysFreeString(month);
  483. V_VT(retv) = VT_BSTR;
  484. V_BSTR(retv) = date_str;
  485. }
  486. return S_OK;
  487. }
  488. /* ECMA-262 3rd Edition 15.9.1.2 */
  489. static HRESULT dateobj_to_string(DateInstance *date, VARIANT *retv)
  490. {
  491. DOUBLE time;
  492. int offset;
  493. time = local_time(date->time, date);
  494. offset = date->bias +
  495. daylight_saving_ta(time, date);
  496. return date_to_string(time, TRUE, offset, retv);
  497. }
  498. static HRESULT Date_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  499. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  500. {
  501. DateInstance *date;
  502. TRACE("\n");
  503. if(!(date = date_this(jsthis)))
  504. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  505. return dateobj_to_string(date, retv);
  506. }
  507. /* ECMA-262 3rd Edition 15.9.1.5 */
  508. static HRESULT Date_toLocaleString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  509. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  510. {
  511. static const WCHAR NaNW[] = { 'N','a','N',0 };
  512. SYSTEMTIME st;
  513. DateInstance *date;
  514. BSTR date_str;
  515. int date_len, time_len;
  516. TRACE("\n");
  517. if(!(date = date_this(jsthis)))
  518. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  519. if(isnan(date->time)) {
  520. if(retv) {
  521. V_VT(retv) = VT_BSTR;
  522. V_BSTR(retv) = SysAllocString(NaNW);
  523. if(!V_BSTR(retv))
  524. return E_OUTOFMEMORY;
  525. }
  526. return S_OK;
  527. }
  528. st = create_systemtime(local_time(date->time, date));
  529. if(st.wYear<1601 || st.wYear>9999)
  530. return dateobj_to_string(date, retv);
  531. if(retv) {
  532. date_len = GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, NULL, 0);
  533. time_len = GetTimeFormatW(ctx->lcid, 0, &st, NULL, NULL, 0);
  534. date_str = SysAllocStringLen(NULL, date_len+time_len-1);
  535. if(!date_str)
  536. return E_OUTOFMEMORY;
  537. GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, date_str, date_len);
  538. GetTimeFormatW(ctx->lcid, 0, &st, NULL, &date_str[date_len], time_len);
  539. date_str[date_len-1] = ' ';
  540. V_VT(retv) = VT_BSTR;
  541. V_BSTR(retv) = date_str;
  542. }
  543. return S_OK;
  544. }
  545. static HRESULT Date_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  546. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  547. {
  548. DateInstance *date;
  549. TRACE("\n");
  550. if(!(date = date_this(jsthis)))
  551. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  552. if(retv)
  553. num_set_val(retv, date->time);
  554. return S_OK;
  555. }
  556. static inline HRESULT create_utc_string(script_ctx_t *ctx, vdisp_t *jsthis,
  557. VARIANT *retv, jsexcept_t *ei)
  558. {
  559. static const WCHAR NaNW[] = { 'N','a','N',0 };
  560. static const WCHAR formatADW[] = { '%','s',',',' ','%','d',' ','%','s',' ','%','d',' ',
  561. '%','0','2','d',':','%','0','2','d',':','%','0','2','d',' ','U','T','C',0 };
  562. static const WCHAR formatBCW[] = { '%','s',',',' ','%','d',' ','%','s',' ','%','d',' ','B','.','C','.',' ',
  563. '%','0','2','d',':','%','0','2','d',':','%','0','2','d',' ','U','T','C',0 };
  564. static const DWORD week_ids[] = { LOCALE_SABBREVDAYNAME7, LOCALE_SABBREVDAYNAME1,
  565. LOCALE_SABBREVDAYNAME2, LOCALE_SABBREVDAYNAME3, LOCALE_SABBREVDAYNAME4,
  566. LOCALE_SABBREVDAYNAME5, LOCALE_SABBREVDAYNAME6 };
  567. static const DWORD month_ids[] = { LOCALE_SABBREVMONTHNAME1, LOCALE_SABBREVMONTHNAME2,
  568. LOCALE_SABBREVMONTHNAME3, LOCALE_SABBREVMONTHNAME4,
  569. LOCALE_SABBREVMONTHNAME5, LOCALE_SABBREVMONTHNAME6,
  570. LOCALE_SABBREVMONTHNAME7, LOCALE_SABBREVMONTHNAME8,
  571. LOCALE_SABBREVMONTHNAME9, LOCALE_SABBREVMONTHNAME10,
  572. LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12 };
  573. BOOL formatAD = TRUE;
  574. BSTR week, month;
  575. DateInstance *date;
  576. BSTR date_str;
  577. int len, size, year, day;
  578. DWORD lcid_en, week_id, month_id;
  579. if(!(date = date_this(jsthis)))
  580. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  581. if(isnan(date->time)) {
  582. if(retv) {
  583. V_VT(retv) = VT_BSTR;
  584. V_BSTR(retv) = SysAllocString(NaNW);
  585. if(!V_BSTR(retv))
  586. return E_OUTOFMEMORY;
  587. }
  588. return S_OK;
  589. }
  590. if(retv) {
  591. len = 17;
  592. lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT);
  593. week_id = week_ids[(int)week_day(date->time)];
  594. size = GetLocaleInfoW(lcid_en, week_id, NULL, 0);
  595. week = SysAllocStringLen(NULL, size);
  596. if(!week)
  597. return E_OUTOFMEMORY;
  598. GetLocaleInfoW(lcid_en, week_id, week, size);
  599. len += size-1;
  600. month_id = month_ids[(int)month_from_time(date->time)];
  601. size = GetLocaleInfoW(lcid_en, month_id, NULL, 0);
  602. month = SysAllocStringLen(NULL, size);
  603. if(!month) {
  604. SysFreeString(week);
  605. return E_OUTOFMEMORY;
  606. }
  607. GetLocaleInfoW(lcid_en, month_id, month, size);
  608. len += size-1;
  609. year = year_from_time(date->time);
  610. if(year<0)
  611. year = -year+1;
  612. do {
  613. year /= 10;
  614. len++;
  615. } while(year);
  616. year = year_from_time(date->time);
  617. if(year<0) {
  618. formatAD = FALSE;
  619. year = -year+1;
  620. len += 5;
  621. }
  622. day = date_from_time(date->time);
  623. do {
  624. day /= 10;
  625. len++;
  626. } while(day);
  627. day = date_from_time(date->time);
  628. date_str = SysAllocStringLen(NULL, len);
  629. if(!date_str) {
  630. SysFreeString(week);
  631. SysFreeString(month);
  632. return E_OUTOFMEMORY;
  633. }
  634. sprintfW(date_str, formatAD?formatADW:formatBCW, week, day, month, year,
  635. (int)hour_from_time(date->time), (int)min_from_time(date->time),
  636. (int)sec_from_time(date->time));
  637. SysFreeString(week);
  638. SysFreeString(month);
  639. V_VT(retv) = VT_BSTR;
  640. V_BSTR(retv) = date_str;
  641. }
  642. return S_OK;
  643. }
  644. /* ECMA-262 3rd Edition 15.9.5.42 */
  645. static HRESULT Date_toUTCString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  646. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  647. {
  648. TRACE("\n");
  649. return create_utc_string(ctx, jsthis, retv, ei);
  650. }
  651. static HRESULT Date_toGMTString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  652. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  653. {
  654. TRACE("\n");
  655. return create_utc_string(ctx, jsthis, retv, ei);
  656. }
  657. /* ECMA-262 3rd Edition 15.9.5.3 */
  658. static HRESULT dateobj_to_date_string(DateInstance *date, VARIANT *retv)
  659. {
  660. static const WCHAR NaNW[] = { 'N','a','N',0 };
  661. static const WCHAR formatADW[] = { '%','s',' ','%','s',' ','%','d',' ','%','d',0 };
  662. static const WCHAR formatBCW[] = { '%','s',' ','%','s',' ','%','d',' ','%','d',' ','B','.','C','.',0 };
  663. static const DWORD week_ids[] = { LOCALE_SABBREVDAYNAME7, LOCALE_SABBREVDAYNAME1,
  664. LOCALE_SABBREVDAYNAME2, LOCALE_SABBREVDAYNAME3, LOCALE_SABBREVDAYNAME4,
  665. LOCALE_SABBREVDAYNAME5, LOCALE_SABBREVDAYNAME6 };
  666. static const DWORD month_ids[] = { LOCALE_SABBREVMONTHNAME1, LOCALE_SABBREVMONTHNAME2,
  667. LOCALE_SABBREVMONTHNAME3, LOCALE_SABBREVMONTHNAME4,
  668. LOCALE_SABBREVMONTHNAME5, LOCALE_SABBREVMONTHNAME6,
  669. LOCALE_SABBREVMONTHNAME7, LOCALE_SABBREVMONTHNAME8,
  670. LOCALE_SABBREVMONTHNAME9, LOCALE_SABBREVMONTHNAME10,
  671. LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12 };
  672. BOOL formatAD = TRUE;
  673. BSTR week, month;
  674. BSTR date_str;
  675. DOUBLE time;
  676. int len, size, year, day;
  677. DWORD lcid_en, week_id, month_id;
  678. if(isnan(date->time)) {
  679. if(retv) {
  680. V_VT(retv) = VT_BSTR;
  681. V_BSTR(retv) = SysAllocString(NaNW);
  682. if(!V_BSTR(retv))
  683. return E_OUTOFMEMORY;
  684. }
  685. return S_OK;
  686. }
  687. time = local_time(date->time, date);
  688. if(retv) {
  689. len = 5;
  690. lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT);
  691. week_id = week_ids[(int)week_day(time)];
  692. size = GetLocaleInfoW(lcid_en, week_id, NULL, 0);
  693. week = SysAllocStringLen(NULL, size);
  694. if(!week)
  695. return E_OUTOFMEMORY;
  696. GetLocaleInfoW(lcid_en, week_id, week, size);
  697. len += size-1;
  698. month_id = month_ids[(int)month_from_time(time)];
  699. size = GetLocaleInfoW(lcid_en, month_id, NULL, 0);
  700. month = SysAllocStringLen(NULL, size);
  701. if(!month) {
  702. SysFreeString(week);
  703. return E_OUTOFMEMORY;
  704. }
  705. GetLocaleInfoW(lcid_en, month_id, month, size);
  706. len += size-1;
  707. year = year_from_time(time);
  708. if(year<0)
  709. year = -year+1;
  710. do {
  711. year /= 10;
  712. len++;
  713. } while(year);
  714. year = year_from_time(time);
  715. if(year<0) {
  716. formatAD = FALSE;
  717. year = -year+1;
  718. len += 5;
  719. }
  720. day = date_from_time(time);
  721. do {
  722. day /= 10;
  723. len++;
  724. } while(day);
  725. day = date_from_time(time);
  726. date_str = SysAllocStringLen(NULL, len);
  727. if(!date_str) {
  728. SysFreeString(week);
  729. SysFreeString(month);
  730. return E_OUTOFMEMORY;
  731. }
  732. sprintfW(date_str, formatAD?formatADW:formatBCW, week, month, day, year);
  733. SysFreeString(week);
  734. SysFreeString(month);
  735. V_VT(retv) = VT_BSTR;
  736. V_BSTR(retv) = date_str;
  737. }
  738. return S_OK;
  739. }
  740. static HRESULT Date_toDateString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  741. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  742. {
  743. DateInstance *date;
  744. if(!(date = date_this(jsthis)))
  745. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  746. return dateobj_to_date_string(date, retv);
  747. }
  748. /* ECMA-262 3rd Edition 15.9.5.4 */
  749. static HRESULT Date_toTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  750. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  751. {
  752. static const WCHAR NaNW[] = { 'N','a','N',0 };
  753. static const WCHAR formatW[] = { '%','0','2','d',':','%','0','2','d',':','%','0','2','d',
  754. ' ','U','T','C','%','c','%','0','2','d','%','0','2','d',0 };
  755. static const WCHAR formatUTCW[] = { '%','0','2','d',':','%','0','2','d',
  756. ':','%','0','2','d',' ','U','T','C',0 };
  757. DateInstance *date;
  758. BSTR date_str;
  759. DOUBLE time;
  760. WCHAR sign;
  761. int offset;
  762. TRACE("\n");
  763. if(!(date = date_this(jsthis)))
  764. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  765. if(isnan(date->time)) {
  766. if(retv) {
  767. V_VT(retv) = VT_BSTR;
  768. V_BSTR(retv) = SysAllocString(NaNW);
  769. if(!V_BSTR(retv))
  770. return E_OUTOFMEMORY;
  771. }
  772. return S_OK;
  773. }
  774. time = local_time(date->time, date);
  775. if(retv) {
  776. date_str = SysAllocStringLen(NULL, 17);
  777. if(!date_str)
  778. return E_OUTOFMEMORY;
  779. offset = date->bias +
  780. daylight_saving_ta(time, date);
  781. if(offset < 0) {
  782. sign = '+';
  783. offset = -offset;
  784. }
  785. else sign = '-';
  786. if(offset)
  787. sprintfW(date_str, formatW, (int)hour_from_time(time),
  788. (int)min_from_time(time), (int)sec_from_time(time),
  789. sign, offset/60, offset%60);
  790. else
  791. sprintfW(date_str, formatUTCW, (int)hour_from_time(time),
  792. (int)min_from_time(time), (int)sec_from_time(time));
  793. V_VT(retv) = VT_BSTR;
  794. V_BSTR(retv) = date_str;
  795. }
  796. return S_OK;
  797. }
  798. /* ECMA-262 3rd Edition 15.9.5.6 */
  799. static HRESULT Date_toLocaleDateString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  800. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  801. {
  802. static const WCHAR NaNW[] = { 'N','a','N',0 };
  803. SYSTEMTIME st;
  804. DateInstance *date;
  805. BSTR date_str;
  806. int len;
  807. TRACE("\n");
  808. if(!(date = date_this(jsthis)))
  809. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  810. if(isnan(date->time)) {
  811. if(retv) {
  812. V_VT(retv) = VT_BSTR;
  813. V_BSTR(retv) = SysAllocString(NaNW);
  814. if(!V_BSTR(retv))
  815. return E_OUTOFMEMORY;
  816. }
  817. return S_OK;
  818. }
  819. st = create_systemtime(local_time(date->time, date));
  820. if(st.wYear<1601 || st.wYear>9999)
  821. return dateobj_to_date_string(date, retv);
  822. if(retv) {
  823. len = GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, NULL, 0);
  824. date_str = SysAllocStringLen(NULL, len);
  825. if(!date_str)
  826. return E_OUTOFMEMORY;
  827. GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, date_str, len);
  828. V_VT(retv) = VT_BSTR;
  829. V_BSTR(retv) = date_str;
  830. }
  831. return S_OK;
  832. }
  833. /* ECMA-262 3rd Edition 15.9.5.7 */
  834. static HRESULT Date_toLocaleTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  835. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  836. {
  837. static const WCHAR NaNW[] = { 'N','a','N',0 };
  838. SYSTEMTIME st;
  839. DateInstance *date;
  840. BSTR date_str;
  841. int len;
  842. TRACE("\n");
  843. if(!(date = date_this(jsthis)))
  844. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  845. if(isnan(date->time)) {
  846. if(retv) {
  847. V_VT(retv) = VT_BSTR;
  848. V_BSTR(retv) = SysAllocString(NaNW);
  849. if(!V_BSTR(retv))
  850. return E_OUTOFMEMORY;
  851. }
  852. return S_OK;
  853. }
  854. st = create_systemtime(local_time(date->time, date));
  855. if(st.wYear<1601 || st.wYear>9999)
  856. return Date_toTimeString(ctx, jsthis, flags, dp, retv, ei, caller);
  857. if(retv) {
  858. len = GetTimeFormatW(ctx->lcid, 0, &st, NULL, NULL, 0);
  859. date_str = SysAllocStringLen(NULL, len);
  860. if(!date_str)
  861. return E_OUTOFMEMORY;
  862. GetTimeFormatW(ctx->lcid, 0, &st, NULL, date_str, len);
  863. V_VT(retv) = VT_BSTR;
  864. V_BSTR(retv) = date_str;
  865. }
  866. return S_OK;
  867. }
  868. /* ECMA-262 3rd Edition 15.9.5.9 */
  869. static HRESULT Date_getTime(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  870. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  871. {
  872. DateInstance *date;
  873. TRACE("\n");
  874. if(!(date = date_this(jsthis)))
  875. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  876. if(retv)
  877. num_set_val(retv, date->time);
  878. return S_OK;
  879. }
  880. /* ECMA-262 3rd Edition 15.9.5.10 */
  881. static HRESULT Date_getFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  882. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  883. {
  884. DateInstance *date;
  885. TRACE("\n");
  886. if(!(date = date_this(jsthis)))
  887. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  888. if(retv) {
  889. DOUBLE time = local_time(date->time, date);
  890. num_set_val(retv, year_from_time(time));
  891. }
  892. return S_OK;
  893. }
  894. /* ECMA-262 3rd Edition 15.9.5.11 */
  895. static HRESULT Date_getUTCFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  896. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  897. {
  898. DateInstance *date;
  899. TRACE("\n");
  900. if(!(date = date_this(jsthis)))
  901. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  902. if(retv)
  903. num_set_val(retv, year_from_time(date->time));
  904. return S_OK;
  905. }
  906. /* ECMA-262 3rd Edition 15.9.5.12 */
  907. static HRESULT Date_getMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  908. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  909. {
  910. DateInstance *date;
  911. TRACE("\n");
  912. if(!(date = date_this(jsthis)))
  913. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  914. if(retv) {
  915. DOUBLE time = local_time(date->time, date);
  916. num_set_val(retv, month_from_time(time));
  917. }
  918. return S_OK;
  919. }
  920. /* ECMA-262 3rd Edition 15.9.5.13 */
  921. static HRESULT Date_getUTCMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  922. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  923. {
  924. DateInstance *date;
  925. TRACE("\n");
  926. if(!(date = date_this(jsthis)))
  927. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  928. if(retv)
  929. num_set_val(retv, month_from_time(date->time));
  930. return S_OK;
  931. }
  932. /* ECMA-262 3rd Edition 15.9.5.14 */
  933. static HRESULT Date_getDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  934. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  935. {
  936. DateInstance *date;
  937. TRACE("\n");
  938. if(!(date = date_this(jsthis)))
  939. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  940. if(retv) {
  941. DOUBLE time = local_time(date->time, date);
  942. num_set_val(retv, date_from_time(time));
  943. }
  944. return S_OK;
  945. }
  946. /* ECMA-262 3rd Edition 15.9.5.15 */
  947. static HRESULT Date_getUTCDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  948. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  949. {
  950. DateInstance *date;
  951. TRACE("\n");
  952. if(!(date = date_this(jsthis)))
  953. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  954. if(retv)
  955. num_set_val(retv, date_from_time(date->time));
  956. return S_OK;
  957. }
  958. /* ECMA-262 3rd Edition 15.9.5.16 */
  959. static HRESULT Date_getDay(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  960. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  961. {
  962. DateInstance *date;
  963. TRACE("\n");
  964. if(!(date = date_this(jsthis)))
  965. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  966. if(retv) {
  967. DOUBLE time = local_time(date->time, date);
  968. num_set_val(retv, week_day(time));
  969. }
  970. return S_OK;
  971. }
  972. /* ECMA-262 3rd Edition 15.9.5.17 */
  973. static HRESULT Date_getUTCDay(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  974. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  975. {
  976. DateInstance *date;
  977. TRACE("\n");
  978. if(!(date = date_this(jsthis)))
  979. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  980. if(retv)
  981. num_set_val(retv, week_day(date->time));
  982. return S_OK;
  983. }
  984. /* ECMA-262 3rd Edition 15.9.5.18 */
  985. static HRESULT Date_getHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  986. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  987. {
  988. DateInstance *date;
  989. TRACE("\n");
  990. if(!(date = date_this(jsthis)))
  991. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  992. if(retv) {
  993. DOUBLE time = local_time(date->time, date);
  994. num_set_val(retv, hour_from_time(time));
  995. }
  996. return S_OK;
  997. }
  998. /* ECMA-262 3rd Edition 15.9.5.19 */
  999. static HRESULT Date_getUTCHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  1000. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  1001. {
  1002. DateInstance *date;
  1003. TRACE("\n");
  1004. if(!(date = date_this(jsthis)))
  1005. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  1006. if(retv)
  1007. num_set_val(retv, hour_from_time(date->time));
  1008. return S_OK;
  1009. }
  1010. /* ECMA-262 3rd Edition 15.9.5.20 */
  1011. static HRESULT Date_getMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  1012. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  1013. {
  1014. DateInstance *date;
  1015. TRACE("\n");
  1016. if(!(date = date_this(jsthis)))
  1017. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  1018. if(retv) {
  1019. DOUBLE time = local_time(date->time, date);
  1020. num_set_val(retv, min_from_time(time));
  1021. }
  1022. return S_OK;
  1023. }
  1024. /* ECMA-262 3rd Edition 15.9.5.21 */
  1025. static HRESULT Date_getUTCMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  1026. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  1027. {
  1028. DateInstance *date;
  1029. TRACE("\n");
  1030. if(!(date = date_this(jsthis)))
  1031. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  1032. if(retv)
  1033. num_set_val(retv, min_from_time(date->time));
  1034. return S_OK;
  1035. }
  1036. /* ECMA-262 3rd Edition 15.9.5.22 */
  1037. static HRESULT Date_getSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  1038. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  1039. {
  1040. DateInstance *date;
  1041. TRACE("\n");
  1042. if(!(date = date_this(jsthis)))
  1043. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  1044. if(retv) {
  1045. DOUBLE time = local_time(date->time, date);
  1046. num_set_val(retv, sec_from_time(time));
  1047. }
  1048. return S_OK;
  1049. }
  1050. /* ECMA-262 3rd Edition 15.9.5.23 */
  1051. static HRESULT Date_getUTCSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  1052. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  1053. {
  1054. DateInstance *date;
  1055. TRACE("\n");
  1056. if(!(date = date_this(jsthis)))
  1057. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  1058. if(retv)
  1059. num_set_val(retv, sec_from_time(date->time));
  1060. return S_OK;
  1061. }
  1062. /* ECMA-262 3rd Edition 15.9.5.24 */
  1063. static HRESULT Date_getMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  1064. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  1065. {
  1066. DateInstance *date;
  1067. TRACE("\n");
  1068. if(!(date = date_this(jsthis)))
  1069. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  1070. if(retv) {
  1071. DOUBLE time = local_time(date->time, date);
  1072. num_set_val(retv, ms_from_time(time));
  1073. }
  1074. return S_OK;
  1075. }
  1076. /* ECMA-262 3rd Edition 15.9.5.25 */
  1077. static HRESULT Date_getUTCMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  1078. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  1079. {
  1080. DateInstance *date;
  1081. TRACE("\n");
  1082. if(!(date = date_this(jsthis)))
  1083. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  1084. if(retv)
  1085. num_set_val(retv, ms_from_time(date->time));
  1086. return S_OK;
  1087. }
  1088. /* ECMA-262 3rd Edition 15.9.5.26 */
  1089. static HRESULT Date_getTimezoneOffset(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  1090. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  1091. {
  1092. DateInstance *date;
  1093. TRACE("\n");
  1094. if(!(date = date_this(jsthis)))
  1095. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  1096. if(retv)
  1097. num_set_val(retv, floor(
  1098. (date->time-local_time(date->time, date))/MS_PER_MINUTE));
  1099. return S_OK;
  1100. }
  1101. /* ECMA-262 3rd Edition 15.9.5.27 */
  1102. static HRESULT Date_setTime(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  1103. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  1104. {
  1105. VARIANT v;
  1106. HRESULT hres;
  1107. DateInstance *date;
  1108. TRACE("\n");
  1109. if(!(date = date_this(jsthis)))
  1110. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  1111. if(!arg_cnt(dp))
  1112. return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
  1113. hres = to_number(ctx, get_arg(dp, 0), ei, &v);
  1114. if(FAILED(hres))
  1115. return hres;
  1116. date->time = time_clip(num_val(&v));
  1117. if(retv)
  1118. num_set_val(retv, date->time);
  1119. return S_OK;
  1120. }
  1121. /* ECMA-262 3rd Edition 15.9.5.28 */
  1122. static HRESULT Date_setMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  1123. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  1124. {
  1125. VARIANT v;
  1126. HRESULT hres;
  1127. DateInstance *date;
  1128. DOUBLE t;
  1129. TRACE("\n");
  1130. if(!(date = date_this(jsthis)))
  1131. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  1132. if(!arg_cnt(dp))
  1133. return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
  1134. hres = to_number(ctx, get_arg(dp, 0), ei, &v);
  1135. if(FAILED(hres))
  1136. return hres;
  1137. t = local_time(date->time, date);
  1138. t = make_date(day(t), make_time(hour_from_time(t), min_from_time(t),
  1139. sec_from_time(t), num_val(&v)));
  1140. date->time = time_clip(utc(t, date));
  1141. if(retv)
  1142. num_set_val(retv, date->time);
  1143. return S_OK;
  1144. }
  1145. /* ECMA-262 3rd Edition 15.9.5.29 */
  1146. static HRESULT Date_setUTCMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  1147. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  1148. {
  1149. VARIANT v;
  1150. HRESULT hres;
  1151. DateInstance *date;
  1152. DOUBLE t;
  1153. TRACE("\n");
  1154. if(!(date = date_this(jsthis)))
  1155. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  1156. if(!arg_cnt(dp))
  1157. return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
  1158. hres = to_number(ctx, get_arg(dp, 0), ei, &v);
  1159. if(FAILED(hres))
  1160. return hres;
  1161. t = date->time;
  1162. t = make_date(day(t), make_time(hour_from_time(t), min_from_time(t),
  1163. sec_from_time(t), num_val(&v)));
  1164. date->time = time_clip(t);
  1165. if(retv)
  1166. num_set_val(retv, date->time);
  1167. return S_OK;
  1168. }
  1169. /* ECMA-262 3rd Edition 15.9.5.30 */
  1170. static HRESULT Date_setSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  1171. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  1172. {
  1173. VARIANT v;
  1174. HRESULT hres;
  1175. DateInstance *date;
  1176. DOUBLE t, sec, ms;
  1177. TRACE("\n");
  1178. if(!(date = date_this(jsthis)))
  1179. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  1180. if(!arg_cnt(dp))
  1181. return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
  1182. t = local_time(date->time, date);
  1183. hres = to_number(ctx, get_arg(dp, 0), ei, &v);
  1184. if(FAILED(hres))
  1185. return hres;
  1186. sec = num_val(&v);
  1187. if(arg_cnt(dp) > 1) {
  1188. hres = to_number(ctx, get_arg(dp, 1), ei, &v);
  1189. if(FAILED(hres))
  1190. return hres;
  1191. ms = num_val(&v);
  1192. }
  1193. else ms = ms_from_time(t);
  1194. t = make_date(day(t), make_time(hour_from_time(t),
  1195. min_from_time(t), sec, ms));
  1196. date->time = time_clip(utc(t, date));
  1197. if(retv)
  1198. num_set_val(retv, date->time);
  1199. return S_OK;
  1200. }
  1201. /* ECMA-262 3rd Edition 15.9.5.31 */
  1202. static HRESULT Date_setUTCSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  1203. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  1204. {
  1205. VARIANT v;
  1206. HRESULT hres;
  1207. DateInstance *date;
  1208. DOUBLE t, sec, ms;
  1209. TRACE("\n");
  1210. if(!(date = date_this(jsthis)))
  1211. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  1212. if(!arg_cnt(dp))
  1213. return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
  1214. t = date->time;
  1215. hres = to_number(ctx, get_arg(dp, 0), ei, &v);
  1216. if(FAILED(hres))
  1217. return hres;
  1218. sec = num_val(&v);
  1219. if(arg_cnt(dp) > 1) {
  1220. hres = to_number(ctx, get_arg(dp, 1), ei, &v);
  1221. if(FAILED(hres))
  1222. return hres;
  1223. ms = num_val(&v);
  1224. }
  1225. else ms = ms_from_time(t);
  1226. t = make_date(day(t), make_time(hour_from_time(t),
  1227. min_from_time(t), sec, ms));
  1228. date->time = time_clip(t);
  1229. if(retv)
  1230. num_set_val(retv, date->time);
  1231. return S_OK;
  1232. }
  1233. /* ECMA-262 3rd Edition 15.9.5.33 */
  1234. static HRESULT Date_setMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  1235. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  1236. {
  1237. VARIANT v;
  1238. HRESULT hres;
  1239. DateInstance *date;
  1240. DOUBLE t, min, sec, ms;
  1241. TRACE("\n");
  1242. if(!(date = date_this(jsthis)))
  1243. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  1244. if(!arg_cnt(dp))
  1245. return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
  1246. t = local_time(date->time, date);
  1247. hres = to_number(ctx, get_arg(dp, 0), ei, &v);
  1248. if(FAILED(hres))
  1249. return hres;
  1250. min = num_val(&v);
  1251. if(arg_cnt(dp) > 1) {
  1252. hres = to_number(ctx, get_arg(dp, 1), ei, &v);
  1253. if(FAILED(hres))
  1254. return hres;
  1255. sec = num_val(&v);
  1256. }
  1257. else sec = sec_from_time(t);
  1258. if(arg_cnt(dp) > 2) {
  1259. hres = to_number(ctx, get_arg(dp, 2), ei, &v);
  1260. if(FAILED(hres))
  1261. return hres;
  1262. ms = num_val(&v);
  1263. }
  1264. else ms = ms_from_time(t);
  1265. t = make_date(day(t), make_time(hour_from_time(t),
  1266. min, sec, ms));
  1267. date->time = time_clip(utc(t, date));
  1268. if(retv)
  1269. num_set_val(retv, date->time);
  1270. return S_OK;
  1271. }
  1272. /* ECMA-262 3rd Edition 15.9.5.34 */
  1273. static HRESULT Date_setUTCMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  1274. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  1275. {
  1276. VARIANT v;
  1277. HRESULT hres;
  1278. DateInstance *date;
  1279. DOUBLE t, min, sec, ms;
  1280. TRACE("\n");
  1281. if(!(date = date_this(jsthis)))
  1282. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  1283. if(!arg_cnt(dp))
  1284. return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
  1285. t = date->time;
  1286. hres = to_number(ctx, get_arg(dp, 0), ei, &v);
  1287. if(FAILED(hres))
  1288. return hres;
  1289. min = num_val(&v);
  1290. if(arg_cnt(dp) > 1) {
  1291. hres = to_number(ctx, get_arg(dp, 1), ei, &v);
  1292. if(FAILED(hres))
  1293. return hres;
  1294. sec = num_val(&v);
  1295. }
  1296. else sec = sec_from_time(t);
  1297. if(arg_cnt(dp) > 2) {
  1298. hres = to_number(ctx, get_arg(dp, 2), ei, &v);
  1299. if(FAILED(hres))
  1300. return hres;
  1301. ms = num_val(&v);
  1302. }
  1303. else ms = ms_from_time(t);
  1304. t = make_date(day(t), make_time(hour_from_time(t),
  1305. min, sec, ms));
  1306. date->time = time_clip(t);
  1307. if(retv)
  1308. num_set_val(retv, date->time);
  1309. return S_OK;
  1310. }
  1311. /* ECMA-262 3rd Edition 15.9.5.35 */
  1312. static HRESULT Date_setHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  1313. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  1314. {
  1315. VARIANT v;
  1316. HRESULT hres;
  1317. DateInstance *date;
  1318. DOUBLE t, hour, min, sec, ms;
  1319. TRACE("\n");
  1320. if(!(date = date_this(jsthis)))
  1321. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  1322. if(!arg_cnt(dp))
  1323. return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
  1324. t = local_time(date->time, date);
  1325. hres = to_number(ctx, get_arg(dp, 0), ei, &v);
  1326. if(FAILED(hres))
  1327. return hres;
  1328. hour = num_val(&v);
  1329. if(arg_cnt(dp) > 1) {
  1330. hres = to_number(ctx, get_arg(dp, 1), ei, &v);
  1331. if(FAILED(hres))
  1332. return hres;
  1333. min = num_val(&v);
  1334. }
  1335. else min = min_from_time(t);
  1336. if(arg_cnt(dp) > 2) {
  1337. hres = to_number(ctx, get_arg(dp, 2), ei, &v);
  1338. if(FAILED(hres))
  1339. return hres;
  1340. sec = num_val(&v);
  1341. }
  1342. else sec = sec_from_time(t);
  1343. if(arg_cnt(dp) > 3) {
  1344. hres = to_number(ctx, get_arg(dp, 3), ei, &v);
  1345. if(FAILED(hres))
  1346. return hres;
  1347. ms = num_val(&v);
  1348. }
  1349. else ms = ms_from_time(t);
  1350. t = make_date(day(t), make_time(hour, min, sec, ms));
  1351. date->time = time_clip(utc(t, date));
  1352. if(retv)
  1353. num_set_val(retv, date->time);
  1354. return S_OK;
  1355. }
  1356. /* ECMA-262 3rd Edition 15.9.5.36 */
  1357. static HRESULT Date_setUTCHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  1358. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  1359. {
  1360. DateInstance *date;
  1361. VARIANT v;
  1362. HRESULT hres;
  1363. DOUBLE t, hour, min, sec, ms;
  1364. TRACE("\n");
  1365. if(!(date = date_this(jsthis)))
  1366. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  1367. if(!arg_cnt(dp))
  1368. return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
  1369. t = date->time;
  1370. hres = to_number(ctx, get_arg(dp, 0), ei, &v);
  1371. if(FAILED(hres))
  1372. return hres;
  1373. hour = num_val(&v);
  1374. if(arg_cnt(dp) > 1) {
  1375. hres = to_number(ctx, get_arg(dp, 1), ei, &v);
  1376. if(FAILED(hres))
  1377. return hres;
  1378. min = num_val(&v);
  1379. }
  1380. else min = min_from_time(t);
  1381. if(arg_cnt(dp) > 2) {
  1382. hres = to_number(ctx, get_arg(dp, 2), ei, &v);
  1383. if(FAILED(hres))
  1384. return hres;
  1385. sec = num_val(&v);
  1386. }
  1387. else sec = sec_from_time(t);
  1388. if(arg_cnt(dp) > 3) {
  1389. hres = to_number(ctx, get_arg(dp, 3), ei, &v);
  1390. if(FAILED(hres))
  1391. return hres;
  1392. ms = num_val(&v);
  1393. }
  1394. else ms = ms_from_time(t);
  1395. t = make_date(day(t), make_time(hour, min, sec, ms));
  1396. date->time = time_clip(t);
  1397. if(retv)
  1398. num_set_val(retv, date->time);
  1399. return S_OK;
  1400. }
  1401. /* ECMA-262 3rd Edition 15.9.5.36 */
  1402. static HRESULT Date_setDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  1403. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  1404. {
  1405. VARIANT v;
  1406. HRESULT hres;
  1407. DateInstance *date;
  1408. DOUBLE t;
  1409. TRACE("\n");
  1410. if(!(date = date_this(jsthis)))
  1411. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  1412. if(!arg_cnt(dp))
  1413. return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
  1414. hres = to_number(ctx, get_arg(dp, 0), ei, &v);
  1415. if(FAILED(hres))
  1416. return hres;
  1417. t = local_time(date->time, date);
  1418. t = make_date(make_day(year_from_time(t), month_from_time(t),
  1419. num_val(&v)), time_within_day(t));
  1420. date->time = time_clip(utc(t, date));
  1421. if(retv)
  1422. num_set_val(retv, date->time);
  1423. return S_OK;
  1424. }
  1425. /* ECMA-262 3rd Edition 15.9.5.37 */
  1426. static HRESULT Date_setUTCDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  1427. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  1428. {
  1429. VARIANT v;
  1430. HRESULT hres;
  1431. DateInstance *date;
  1432. DOUBLE t;
  1433. TRACE("\n");
  1434. if(!(date = date_this(jsthis)))
  1435. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  1436. if(!arg_cnt(dp))
  1437. return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
  1438. hres = to_number(ctx, get_arg(dp, 0), ei, &v);
  1439. if(FAILED(hres))
  1440. return hres;
  1441. t = date->time;
  1442. t = make_date(make_day(year_from_time(t), month_from_time(t),
  1443. num_val(&v)), time_within_day(t));
  1444. date->time = time_clip(t);
  1445. if(retv)
  1446. num_set_val(retv, date->time);
  1447. return S_OK;
  1448. }
  1449. /* ECMA-262 3rd Edition 15.9.5.38 */
  1450. static HRESULT Date_setMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  1451. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  1452. {
  1453. VARIANT v;
  1454. HRESULT hres;
  1455. DateInstance *date;
  1456. DOUBLE t, month, ddate;
  1457. TRACE("\n");
  1458. if(!(date = date_this(jsthis)))
  1459. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  1460. if(!arg_cnt(dp))
  1461. return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
  1462. t = local_time(date->time, date);
  1463. hres = to_number(ctx, get_arg(dp, 0), ei, &v);
  1464. if(FAILED(hres))
  1465. return hres;
  1466. month = num_val(&v);
  1467. if(arg_cnt(dp) > 1) {
  1468. hres = to_number(ctx, get_arg(dp, 1), ei, &v);
  1469. if(FAILED(hres))
  1470. return hres;
  1471. ddate = num_val(&v);
  1472. }
  1473. else ddate = date_from_time(t);
  1474. t = make_date(make_day(year_from_time(t), month, ddate),
  1475. time_within_day(t));
  1476. date->time = time_clip(utc(t, date));
  1477. if(retv)
  1478. num_set_val(retv, date->time);
  1479. return S_OK;
  1480. }
  1481. /* ECMA-262 3rd Edition 15.9.5.39 */
  1482. static HRESULT Date_setUTCMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  1483. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  1484. {
  1485. VARIANT v;
  1486. HRESULT hres;
  1487. DateInstance *date;
  1488. DOUBLE t, month, ddate;
  1489. TRACE("\n");
  1490. if(!(date = date_this(jsthis)))
  1491. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  1492. if(!arg_cnt(dp))
  1493. return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
  1494. t = date->time;
  1495. hres = to_number(ctx, get_arg(dp, 0), ei, &v);
  1496. if(FAILED(hres))
  1497. return hres;
  1498. month = num_val(&v);
  1499. if(arg_cnt(dp) > 1) {
  1500. hres = to_number(ctx, get_arg(dp, 1), ei, &v);
  1501. if(FAILED(hres))
  1502. return hres;
  1503. ddate = num_val(&v);
  1504. }
  1505. else ddate = date_from_time(t);
  1506. t = make_date(make_day(year_from_time(t), month, ddate),
  1507. time_within_day(t));
  1508. date->time = time_clip(t);
  1509. if(retv)
  1510. num_set_val(retv, date->time);
  1511. return S_OK;
  1512. }
  1513. /* ECMA-262 3rd Edition 15.9.5.40 */
  1514. static HRESULT Date_setFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  1515. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  1516. {
  1517. VARIANT v;
  1518. HRESULT hres;
  1519. DateInstance *date;
  1520. DOUBLE t, year, month, ddate;
  1521. TRACE("\n");
  1522. if(!(date = date_this(jsthis)))
  1523. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  1524. if(!arg_cnt(dp))
  1525. return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
  1526. t = local_time(date->time, date);
  1527. hres = to_number(ctx, get_arg(dp, 0), ei, &v);
  1528. if(FAILED(hres))
  1529. return hres;
  1530. year = num_val(&v);
  1531. if(arg_cnt(dp) > 1) {
  1532. hres = to_number(ctx, get_arg(dp, 1), ei, &v);
  1533. if(FAILED(hres))
  1534. return hres;
  1535. month = num_val(&v);
  1536. }
  1537. else month = month_from_time(t);
  1538. if(arg_cnt(dp) > 2) {
  1539. hres = to_number(ctx, get_arg(dp, 2), ei, &v);
  1540. if(FAILED(hres))
  1541. return hres;
  1542. ddate = num_val(&v);
  1543. }
  1544. else ddate = date_from_time(t);
  1545. t = make_date(make_day(year, month, ddate), time_within_day(t));
  1546. date->time = time_clip(utc(t, date));
  1547. if(retv)
  1548. num_set_val(retv, date->time);
  1549. return S_OK;
  1550. }
  1551. /* ECMA-262 3rd Edition 15.9.5.41 */
  1552. static HRESULT Date_setUTCFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  1553. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  1554. {
  1555. VARIANT v;
  1556. HRESULT hres;
  1557. DateInstance *date;
  1558. DOUBLE t, year, month, ddate;
  1559. TRACE("\n");
  1560. if(!(date = date_this(jsthis)))
  1561. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  1562. if(!arg_cnt(dp))
  1563. return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
  1564. t = date->time;
  1565. hres = to_number(ctx, get_arg(dp, 0), ei, &v);
  1566. if(FAILED(hres))
  1567. return hres;
  1568. year = num_val(&v);
  1569. if(arg_cnt(dp) > 1) {
  1570. hres = to_number(ctx, get_arg(dp, 1), ei, &v);
  1571. if(FAILED(hres))
  1572. return hres;
  1573. month = num_val(&v);
  1574. }
  1575. else month = month_from_time(t);
  1576. if(arg_cnt(dp) > 2) {
  1577. hres = to_number(ctx, get_arg(dp, 2), ei, &v);
  1578. if(FAILED(hres))
  1579. return hres;
  1580. ddate = num_val(&v);
  1581. }
  1582. else ddate = date_from_time(t);
  1583. t = make_date(make_day(year, month, ddate), time_within_day(t));
  1584. date->time = time_clip(t);
  1585. if(retv)
  1586. num_set_val(retv, date->time);
  1587. return S_OK;
  1588. }
  1589. /* ECMA-262 3rd Edition B2.4 */
  1590. static HRESULT Date_getYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  1591. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  1592. {
  1593. DateInstance *date;
  1594. DOUBLE t, year;
  1595. TRACE("\n");
  1596. if(!(date = date_this(jsthis)))
  1597. return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
  1598. t = local_time(date->time, date);
  1599. if(isnan(t)) {
  1600. if(retv)
  1601. num_set_nan(retv);
  1602. return S_OK;
  1603. }
  1604. year = year_from_time(t);
  1605. if(retv)
  1606. num_set_val(retv, (1900<=year && year<2000)?year-1900:year);
  1607. return S_OK;
  1608. }
  1609. static HRESULT Date_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  1610. VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
  1611. {
  1612. TRACE("\n");
  1613. switch(flags) {
  1614. case INVOKE_FUNC:
  1615. return throw_type_error(ctx, ei, IDS_NOT_FUNC, NULL);
  1616. default:
  1617. FIXME("unimplemented flags %x\n", flags);
  1618. return E_NOTIMPL;
  1619. }
  1620. return S_OK;
  1621. }
  1622. static const builtin_prop_t Date_props[] = {
  1623. {getDateW, Date_getDate, PROPF_METHOD},
  1624. {getDayW, Date_getDay, PROPF_METHOD},
  1625. {getFullYearW, Date_getFullYear, PROPF_METHOD},
  1626. {getHoursW, Date_getHours, PROPF_METHOD},
  1627. {getMillisecondsW, Date_getMilliseconds, PROPF_METHOD},
  1628. {getMinutesW, Date_getMinutes, PROPF_METHOD},
  1629. {getMonthW, Date_getMonth, PROPF_METHOD},
  1630. {getSecondsW, Date_getSeconds, PROPF_METHOD},
  1631. {getTimeW, Date_getTime, PROPF_METHOD},
  1632. {getTimezoneOffsetW, Date_getTimezoneOffset, PROPF_METHOD},
  1633. {getUTCDateW, Date_getUTCDate, PROPF_METHOD},
  1634. {getUTCDayW, Date_getUTCDay, PROPF_METHOD},
  1635. {getUTCFullYearW, Date_getUTCFullYear, PROPF_METHOD},
  1636. {getUTCHoursW, Date_getUTCHours, PROPF_METHOD},
  1637. {getUTCMillisecondsW, Date_getUTCMilliseconds, PROPF_METHOD},
  1638. {getUTCMinutesW, Date_getUTCMinutes, PROPF_METHOD},
  1639. {getUTCMonthW, Date_getUTCMonth, PROPF_METHOD},
  1640. {getUTCSecondsW, Date_getUTCSeconds, PROPF_METHOD},
  1641. {getYearW, Date_getYear, PROPF_METHOD},
  1642. {setDateW, Date_setDate, PROPF_METHOD|1},
  1643. {setFullYearW, Date_setFullYear, PROPF_METHOD|3},
  1644. {setHoursW, Date_setHours, PROPF_METHOD|4},
  1645. {setMillisecondsW, Date_setMilliseconds, PROPF_METHOD|1},
  1646. {setMinutesW, Date_setMinutes, PROPF_METHOD|3},
  1647. {setMonthW, Date_setMonth, PROPF_METHOD|2},
  1648. {setSecondsW, Date_setSeconds, PROPF_METHOD|2},
  1649. {setTimeW, Date_setTime, PROPF_METHOD|1},
  1650. {setUTCDateW, Date_setUTCDate, PROPF_METHOD|1},
  1651. {setUTCFullYearW, Date_setUTCFullYear, PROPF_METHOD|3},
  1652. {setUTCHoursW, Date_setUTCHours, PROPF_METHOD|4},
  1653. {setUTCMillisecondsW, Date_setUTCMilliseconds, PROPF_METHOD|1},
  1654. {setUTCMinutesW, Date_setUTCMinutes, PROPF_METHOD|3},
  1655. {setUTCMonthW, Date_setUTCMonth, PROPF_METHOD|2},
  1656. {setUTCSecondsW, Date_setUTCSeconds, PROPF_METHOD|2},
  1657. {toDateStringW, Date_toDateString, PROPF_METHOD},
  1658. {toGMTStringW, Date_toGMTString, PROPF_METHOD},
  1659. {toLocaleDateStringW, Date_toLocaleDateString, PROPF_METHOD},
  1660. {toLocaleStringW, Date_toLocaleString, PROPF_METHOD},
  1661. {toLocaleTimeStringW, Date_toLocaleTimeString, PROPF_METHOD},
  1662. {toStringW, Date_toString, PROPF_METHOD},
  1663. {toTimeStringW, Date_toTimeString, PROPF_METHOD},
  1664. {toUTCStringW, Date_toUTCString, PROPF_METHOD},
  1665. {valueOfW, Date_valueOf, PROPF_METHOD},
  1666. };
  1667. static const builtin_info_t Date_info = {
  1668. JSCLASS_DATE,
  1669. {NULL, Date_value, 0},
  1670. sizeof(Date_props)/sizeof(*Date_props),
  1671. Date_props,
  1672. NULL,
  1673. NULL
  1674. };
  1675. static HRESULT create_date(script_ctx_t *ctx, DispatchEx *object_prototype, DOUBLE time, DispatchEx **ret)
  1676. {
  1677. DateInstance *date;
  1678. HRESULT hres;
  1679. TIME_ZONE_INFORMATION tzi;
  1680. GetTimeZoneInformation(&tzi);
  1681. date = heap_alloc_zero(sizeof(DateInstance));
  1682. if(!date)
  1683. return E_OUTOFMEMORY;
  1684. if(object_prototype)
  1685. hres = init_dispex(&date->dispex, ctx, &Date_info, object_prototype);
  1686. else
  1687. hres = init_dispex_from_constr(&date->dispex, ctx, &Date_info, ctx->date_constr);
  1688. if(FAILED(hres)) {
  1689. heap_free(date);
  1690. return hres;
  1691. }
  1692. date->time = time;
  1693. date->bias = tzi.Bias;
  1694. date->standardDate = tzi.StandardDate;
  1695. date->standardBias = tzi.StandardBias;
  1696. date->daylightDate = tzi.DaylightDate;
  1697. date->daylightBias = tzi.DaylightBias;
  1698. *ret = &date->dispex;
  1699. return S_OK;
  1700. }
  1701. static inline HRESULT date_parse(BSTR input, VARIANT *retv) {
  1702. static const DWORD string_ids[] = { LOCALE_SMONTHNAME12, LOCALE_SMONTHNAME11,
  1703. LOCALE_SMONTHNAME10, LOCALE_SMONTHNAME9, LOCALE_SMONTHNAME8,
  1704. LOCALE_SMONTHNAME7, LOCALE_SMONTHNAME6, LOCALE_SMONTHNAME5,
  1705. LOCALE_SMONTHNAME4, LOCALE_SMONTHNAME3, LOCALE_SMONTHNAME2,
  1706. LOCALE_SMONTHNAME1, LOCALE_SDAYNAME7, LOCALE_SDAYNAME1,
  1707. LOCALE_SDAYNAME2, LOCALE_SDAYNAME3, LOCALE_SDAYNAME4,
  1708. LOCALE_SDAYNAME5, LOCALE_SDAYNAME6 };
  1709. BSTR strings[sizeof(string_ids)/sizeof(DWORD)];
  1710. BSTR parse;
  1711. int input_len, parse_len = 0, nest_level = 0, i, size;
  1712. int year = 0, month = 0, day = 0, hour = 0, min = 0, sec = 0;
  1713. int ms = 0, offset = 0, hour_adjust = 0;
  1714. BOOL set_year = FALSE, set_month = FALSE, set_day = FALSE, set_hour = FALSE;
  1715. BOOL set_offset = FALSE, set_era = FALSE, ad = TRUE, set_am = FALSE, am = TRUE;
  1716. BOOL set_hour_adjust = TRUE;
  1717. TIME_ZONE_INFORMATION tzi;
  1718. DateInstance di;
  1719. DWORD lcid_en;
  1720. if(retv) num_set_nan(retv);
  1721. input_len = SysStringLen(input);
  1722. for(i=0; i<input_len; i++) {
  1723. if(input[i] == '(') nest_level++;
  1724. else if(input[i] == ')') {
  1725. nest_level--;
  1726. if(nest_level<0)
  1727. return S_OK;
  1728. }
  1729. else if(!nest_level) parse_len++;
  1730. }
  1731. parse = SysAllocStringLen(NULL, parse_len);
  1732. if(!parse)
  1733. return E_OUTOFMEMORY;
  1734. nest_level = 0;
  1735. parse_len = 0;
  1736. for(i=0; i<input_len; i++) {
  1737. if(input[i] == '(') nest_level++;
  1738. else if(input[i] == ')') nest_level--;
  1739. else if(!nest_level) parse[parse_len++] = toupperW(input[i]);
  1740. }
  1741. GetTimeZoneInformation(&tzi);
  1742. di.bias = tzi.Bias;
  1743. di.standardDate = tzi.StandardDate;
  1744. di.standardBias = tzi.StandardBias;
  1745. di.daylightDate = tzi.DaylightDate;
  1746. di.daylightBias = tzi.DaylightBias;
  1747. lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT);
  1748. for(i=0; i<sizeof(string_ids)/sizeof(DWORD); i++) {
  1749. size = GetLocaleInfoW(lcid_en, string_ids[i], NULL, 0);
  1750. strings[i] = SysAllocStringLen(NULL, size);
  1751. if(!strings[i]) {
  1752. i--;
  1753. while(i-- >= 0)
  1754. SysFreeString(strings[i]);
  1755. SysFreeString(parse);
  1756. return E_OUTOFMEMORY;
  1757. }
  1758. GetLocaleInfoW(lcid_en, string_ids[i], strings[i], size);
  1759. }
  1760. for(i=0; i<parse_len;) {
  1761. while(isspaceW(parse[i])) i++;
  1762. if(parse[i] == ',') {
  1763. while(parse[i] == ',') i++;
  1764. continue;
  1765. }
  1766. if(parse[i]>='0' && parse[i]<='9') {
  1767. int tmp = atoiW(&parse[i]);
  1768. while(parse[i]>='0' && parse[i]<='9') i++;
  1769. while(isspaceW(parse[i])) i++;
  1770. if(parse[i] == ':') {
  1771. /* Time */
  1772. if(set_hour) break;
  1773. set_hour = TRUE;
  1774. hour = tmp;
  1775. while(parse[i] == ':') i++;
  1776. while(isspaceW(parse[i])) i++;
  1777. if(parse[i]>='0' && parse[i]<='9') {
  1778. min = atoiW(&parse[i]);
  1779. while(parse[i]>='0' && parse[i]<='9') i++;
  1780. }
  1781. while(isspaceW(parse[i])) i++;
  1782. while(parse[i] == ':') i++;
  1783. while(isspaceW(parse[i])) i++;
  1784. if(parse[i]>='0' && parse[i]<='9') {
  1785. sec = atoiW(&parse[i]);
  1786. while(parse[i]>='0' && parse[i]<='9') i++;
  1787. }
  1788. }
  1789. else if(parse[i]=='-' || parse[i]=='/') {
  1790. /* Short date */
  1791. if(set_day || set_month || set_year) break;
  1792. set_day = TRUE;
  1793. set_month = TRUE;
  1794. set_year = TRUE;
  1795. month = tmp-1;
  1796. while(isspaceW(parse[i])) i++;
  1797. while(parse[i]=='-' || parse[i]=='/') i++;
  1798. while(isspaceW(parse[i])) i++;
  1799. if(parse[i]<'0' || parse[i]>'9') break;
  1800. day = atoiW(&parse[i]);
  1801. while(parse[i]>='0' && parse[i]<='9') i++;
  1802. while(parse[i]=='-' || parse[i]=='/') i++;
  1803. while(isspaceW(parse[i])) i++;
  1804. if(parse[i]<'0' || parse[i]>'9') break;
  1805. year = atoiW(&parse[i]);
  1806. while(parse[i]>='0' && parse[i]<='9') i++;
  1807. }
  1808. else if(tmp<0) break;
  1809. else if(tmp<70) {
  1810. /* Day */
  1811. if(set_day) break;
  1812. set_day = TRUE;
  1813. day = tmp;
  1814. }
  1815. else {
  1816. /* Year */
  1817. if(set_year) break;
  1818. set_year = TRUE;
  1819. year = tmp;
  1820. }
  1821. }
  1822. else {
  1823. if(parse[i]<'A' || parse[i]>'Z') break;
  1824. else if(parse[i]=='B' && (parse[i+1]=='C' ||
  1825. (parse[i+1]=='.' && parse[i+2]=='C'))) {
  1826. /* AD/BC */
  1827. if(set_era) break;
  1828. set_era = TRUE;
  1829. ad = FALSE;
  1830. i++;
  1831. if(parse[i] == '.') i++;
  1832. i++;
  1833. if(parse[i] == '.') i++;
  1834. }
  1835. else if(parse[i]=='A' && (parse[i+1]=='D' ||
  1836. (parse[i+1]=='.' && parse[i+2]=='D'))) {
  1837. /* AD/BC */
  1838. if(set_era) break;
  1839. set_era = TRUE;
  1840. i++;
  1841. if(parse[i] == '.') i++;
  1842. i++;
  1843. if(parse[i] == '.') i++;
  1844. }
  1845. else if(parse[i+1]<'A' || parse[i+1]>'Z') {
  1846. /* Timezone */
  1847. if(set_offset) break;
  1848. set_offset = TRUE;
  1849. if(parse[i] <= 'I') hour_adjust = parse[i]-'A'+2;
  1850. else if(parse[i] == 'J') break;
  1851. else if(parse[i] <= 'M') hour_adjust = parse[i]-'K'+11;
  1852. else if(parse[i] <= 'Y') hour_adjust = parse[i]-'N';
  1853. else hour_adjust = 1;
  1854. i++;
  1855. if(parse[i] == '.') i++;
  1856. }
  1857. else if(parse[i]=='A' && parse[i+1]=='M') {
  1858. /* AM/PM */
  1859. if(set_am) break;
  1860. set_am = TRUE;
  1861. am = TRUE;
  1862. i += 2;
  1863. }
  1864. else if(parse[i]=='P' && parse[i+1]=='M') {
  1865. /* AM/PM */
  1866. if(set_am) break;
  1867. set_am = TRUE;
  1868. am = FALSE;
  1869. i += 2;
  1870. }
  1871. else if((parse[i]=='U' && parse[i+1]=='T' && parse[i+2]=='C')
  1872. || (parse[i]=='G' && parse[i+1]=='M' && parse[i+2]=='T')) {
  1873. /* Timezone */
  1874. BOOL positive = TRUE;
  1875. if(set_offset) break;
  1876. set_offset = TRUE;
  1877. set_hour_adjust = FALSE;
  1878. i += 3;
  1879. while(isspaceW(parse[i])) i++;
  1880. if(parse[i] == '-') positive = FALSE;
  1881. else if(parse[i] != '+') continue;
  1882. i++;
  1883. while(isspaceW(parse[i])) i++;
  1884. if(parse[i]<'0' || parse[i]>'9') break;
  1885. offset = atoiW(&parse[i]);
  1886. while(parse[i]>='0' && parse[i]<='9') i++;
  1887. if(offset<24) offset *= 60;
  1888. else offset = (offset/100)*60 + offset%100;
  1889. if(positive) offset = -offset;
  1890. }
  1891. else {
  1892. /* Month or garbage */
  1893. int j;
  1894. for(size=i; parse[size]>='A' && parse[size]<='Z'; size++);
  1895. size -= i;
  1896. for(j=0; j<sizeof(string_ids)/sizeof(DWORD); j++)
  1897. if(!memicmpW(&parse[i], strings[j], size)) break;
  1898. if(j < 12) {
  1899. if(set_month) break;
  1900. set_month = TRUE;
  1901. month = 11-j;
  1902. }
  1903. else if(j == sizeof(string_ids)/sizeof(DWORD)) break;
  1904. i += size;
  1905. }
  1906. }
  1907. }
  1908. if(retv && i==parse_len && set_year && set_month
  1909. && set_day && (!set_am || hour<13)) {
  1910. if(set_am) {
  1911. if(hour == 12) hour = 0;
  1912. if(!am) hour += 12;
  1913. }
  1914. if(!ad) year = -year+1;
  1915. else if(year<100) year += 1900;
  1916. V_VT(retv) = VT_R8;
  1917. V_R8(retv) = time_clip(make_date(make_day(year, month, day),
  1918. make_time(hour+hour_adjust, min, sec, ms)) + offset*MS_PER_MINUTE);
  1919. if(set_hour_adjust) V_R8(retv) = utc(V_R8(retv), &di);
  1920. }
  1921. for(i=0; i<sizeof(string_ids)/sizeof(DWORD); i++)
  1922. SysFreeString(strings[i]);
  1923. SysFreeString(parse);
  1924. return S_OK;
  1925. }
  1926. static HRESULT DateConstr_parse(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  1927. VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
  1928. {
  1929. BSTR parse_str;
  1930. HRESULT hres;
  1931. TRACE("\n");
  1932. if(!arg_cnt(dp)) {
  1933. if(retv)
  1934. num_set_nan(retv);
  1935. return S_OK;
  1936. }
  1937. hres = to_string(ctx, get_arg(dp,0), ei, &parse_str);
  1938. if(FAILED(hres))
  1939. return hres;
  1940. hres = date_parse(parse_str, retv);
  1941. SysFreeString(parse_str);
  1942. return hres;
  1943. }
  1944. static HRESULT date_utc(script_ctx_t *ctx, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei)
  1945. {
  1946. VARIANT year, month, vdate, hours, minutes, seconds, ms;
  1947. DOUBLE y;
  1948. int arg_no = arg_cnt(dp);
  1949. HRESULT hres;
  1950. TRACE("\n");
  1951. if(arg_no>0) {
  1952. hres = to_number(ctx, get_arg(dp, 0), ei, &year);
  1953. if(FAILED(hres))
  1954. return hres;
  1955. y = num_val(&year);
  1956. if(0<=y && y<=99)
  1957. y += 1900;
  1958. }
  1959. else y = 1900;
  1960. if(arg_no>1) {
  1961. hres = to_number(ctx, get_arg(dp, 1), ei, &month);
  1962. if(FAILED(hres))
  1963. return hres;
  1964. }
  1965. else {
  1966. V_VT(&month) = VT_R8;
  1967. V_R8(&month) = 0;
  1968. }
  1969. if(arg_no>2) {
  1970. hres = to_number(ctx, get_arg(dp, 2), ei, &vdate);
  1971. if(FAILED(hres))
  1972. return hres;
  1973. }
  1974. else {
  1975. V_VT(&vdate) = VT_R8;
  1976. V_R8(&vdate) = 1;
  1977. }
  1978. if(arg_no>3) {
  1979. hres = to_number(ctx, get_arg(dp, 3), ei, &hours);
  1980. if(FAILED(hres))
  1981. return hres;
  1982. }
  1983. else {
  1984. V_VT(&hours) = VT_R8;
  1985. V_R8(&hours) = 0;
  1986. }
  1987. if(arg_no>4) {
  1988. hres = to_number(ctx, get_arg(dp, 4), ei, &minutes);
  1989. if(FAILED(hres))
  1990. return hres;
  1991. }
  1992. else {
  1993. V_VT(&minutes) = VT_R8;
  1994. V_R8(&minutes) = 0;
  1995. }
  1996. if(arg_no>5) {
  1997. hres = to_number(ctx, get_arg(dp, 5), ei, &seconds);
  1998. if(FAILED(hres))
  1999. return hres;
  2000. }
  2001. else {
  2002. V_VT(&seconds) = VT_R8;
  2003. V_R8(&seconds) = 0;
  2004. }
  2005. if(arg_no>6) {
  2006. hres = to_number(ctx, get_arg(dp, 6), ei, &ms);
  2007. if(FAILED(hres))
  2008. return hres;
  2009. }
  2010. else {
  2011. V_VT(&ms) = VT_R8;
  2012. V_R8(&ms) = 0;
  2013. }
  2014. if(retv) {
  2015. V_VT(retv) = VT_R8;
  2016. V_R8(retv) = time_clip(make_date(
  2017. make_day(y, num_val(&month), num_val(&vdate)),
  2018. make_time(num_val(&hours), num_val(&minutes),
  2019. num_val(&seconds), num_val(&ms))));
  2020. }
  2021. return S_OK;
  2022. }
  2023. static HRESULT DateConstr_UTC(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  2024. VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
  2025. {
  2026. TRACE("\n");
  2027. return date_utc(ctx, dp, retv, ei);
  2028. }
  2029. static HRESULT DateConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
  2030. VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
  2031. {
  2032. DispatchEx *date;
  2033. HRESULT hres;
  2034. TRACE("\n");
  2035. switch(flags) {
  2036. case DISPATCH_CONSTRUCT:
  2037. switch(arg_cnt(dp)) {
  2038. /* ECMA-262 3rd Edition 15.9.3.3 */
  2039. case 0: {
  2040. FILETIME time;
  2041. LONGLONG lltime;
  2042. GetSystemTimeAsFileTime(&time);
  2043. lltime = ((LONGLONG)time.dwHighDateTime<<32)
  2044. + time.dwLowDateTime;
  2045. hres = create_date(ctx, NULL, lltime/10000-TIME_EPOCH, &date);
  2046. if(FAILED(hres))
  2047. return hres;
  2048. break;
  2049. }
  2050. /* ECMA-262 3rd Edition 15.9.3.2 */
  2051. case 1: {
  2052. VARIANT prim, num;
  2053. hres = to_primitive(ctx, get_arg(dp,0), ei, &prim, NO_HINT);
  2054. if(FAILED(hres))
  2055. return hres;
  2056. if(V_VT(&prim) == VT_BSTR)
  2057. hres = date_parse(V_BSTR(&prim), &num);
  2058. else
  2059. hres = to_number(ctx, &prim, ei, &num);
  2060. VariantClear(&prim);
  2061. if(FAILED(hres))
  2062. return hres;
  2063. hres = create_date(ctx, NULL, time_clip(num_val(&num)), &date);
  2064. if(FAILED(hres))
  2065. return hres;
  2066. break;
  2067. }
  2068. /* ECMA-262 3rd Edition 15.9.3.1 */
  2069. default: {
  2070. VARIANT ret_date;
  2071. DateInstance *di;
  2072. hres = date_utc(ctx, dp, &ret_date, ei);
  2073. if(FAILED(hres))
  2074. return hres;
  2075. hres = create_date(ctx, NULL, num_val(&ret_date), &date);
  2076. if(FAILED(hres))
  2077. return hres;
  2078. di = (DateInstance*)date;
  2079. di->time = utc(di->time, di);
  2080. }
  2081. }
  2082. V_VT(retv) = VT_DISPATCH;
  2083. V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(date);
  2084. return S_OK;
  2085. case INVOKE_FUNC: {
  2086. FILETIME system_time, local_time;
  2087. LONGLONG lltime;
  2088. GetSystemTimeAsFileTime(&system_time);
  2089. FileTimeToLocalFileTime(&system_time, &local_time);
  2090. lltime = ((LONGLONG)local_time.dwHighDateTime<<32)
  2091. + local_time.dwLowDateTime;
  2092. return date_to_string(lltime/10000-TIME_EPOCH, FALSE, 0, retv);
  2093. }
  2094. default:
  2095. FIXME("unimplemented flags %x\n", flags);
  2096. return E_NOTIMPL;
  2097. }
  2098. return S_OK;
  2099. }
  2100. static const builtin_prop_t DateConstr_props[] = {
  2101. {UTCW, DateConstr_UTC, PROPF_METHOD},
  2102. {parseW, DateConstr_parse, PROPF_METHOD}
  2103. };
  2104. static const builtin_info_t DateConstr_info = {
  2105. JSCLASS_FUNCTION,
  2106. {NULL, Function_value, 0},
  2107. sizeof(DateConstr_props)/sizeof(*DateConstr_props),
  2108. DateConstr_props,
  2109. NULL,
  2110. NULL
  2111. };
  2112. HRESULT create_date_constr(script_ctx_t *ctx, DispatchEx *object_prototype, DispatchEx **ret)
  2113. {
  2114. DispatchEx *date;
  2115. HRESULT hres;
  2116. static const WCHAR DateW[] = {'D','a','t','e',0};
  2117. hres = create_date(ctx, object_prototype, 0.0, &date);
  2118. if(FAILED(hres))
  2119. return hres;
  2120. hres = create_builtin_function(ctx, DateConstr_value, DateW, &DateConstr_info,
  2121. PROPF_CONSTR|7, date, ret);
  2122. jsdisp_release(date);
  2123. return hres;
  2124. }