jscript: Fix typos in comments, add missing ones.
[wine] / dlls / jscript / date.c
1 /*
2  * Copyright 2008 Jacek Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include <limits.h>
20 #include <math.h>
21
22 #include "jscript.h"
23
24 #include "wine/debug.h"
25
26 WINE_DEFAULT_DEBUG_CHANNEL(jscript);
27
28 /* 1601 to 1970 is 369 years plus 89 leap days */
29 #define TIME_EPOCH  ((ULONGLONG)(369 * 365 + 89) * 86400 * 1000)
30
31 typedef struct {
32     DispatchEx dispex;
33
34     /* ECMA-262 3rd Edition    15.9.1.1 */
35     DOUBLE time;
36
37     LONG bias;
38     SYSTEMTIME standardDate;
39     LONG standardBias;
40     SYSTEMTIME daylightDate;
41     LONG daylightBias;
42 } DateInstance;
43
44 static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0};
45 static const WCHAR toLocaleStringW[] = {'t','o','L','o','c','a','l','e','S','t','r','i','n','g',0};
46 static const WCHAR hasOwnPropertyW[] = {'h','a','s','O','w','n','P','r','o','p','e','r','t','y',0};
47 static const WCHAR propertyIsEnumerableW[] =
48     {'p','r','o','p','e','r','t','y','I','s','E','n','u','m','e','r','a','b','l','e',0};
49 static const WCHAR isPrototypeOfW[] = {'i','s','P','r','o','t','o','t','y','p','e','O','f',0};
50 static const WCHAR valueOfW[] = {'v','a','l','u','e','O','f',0};
51 static const WCHAR toUTCStringW[] = {'t','o','U','T','C','S','t','r','i','n','g',0};
52 static const WCHAR toDateStringW[] = {'t','o','D','a','t','e','S','t','r','i','n','g',0};
53 static const WCHAR toTimeStringW[] = {'t','o','T','i','m','e','S','t','r','i','n','g',0};
54 static const WCHAR toLocaleDateStringW[] = {'t','o','L','o','c','a','l','e','D','a','t','e','S','t','r','i','n','g',0};
55 static const WCHAR toLocaleTimeStringW[] = {'t','o','L','o','c','a','l','e','T','i','m','e','S','t','r','i','n','g',0};
56 static const WCHAR getTimeW[] = {'g','e','t','T','i','m','e',0};
57 static const WCHAR getFullYearW[] = {'g','e','t','F','u','l','l','Y','e','a','r',0};
58 static const WCHAR getUTCFullYearW[] = {'g','e','t','U','T','C','F','u','l','l','Y','e','a','r',0};
59 static const WCHAR getMonthW[] = {'g','e','t','M','o','n','t','h',0};
60 static const WCHAR getUTCMonthW[] = {'g','e','t','U','T','C','M','o','n','t','h',0};
61 static const WCHAR getDateW[] = {'g','e','t','D','a','t','e',0};
62 static const WCHAR getUTCDateW[] = {'g','e','t','U','T','C','D','a','t','e',0};
63 static const WCHAR getDayW[] = {'g','e','t','D','a','y',0};
64 static const WCHAR getUTCDayW[] = {'g','e','t','U','T','C','D','a','y',0};
65 static const WCHAR getHoursW[] = {'g','e','t','H','o','u','r','s',0};
66 static const WCHAR getUTCHoursW[] = {'g','e','t','U','T','C','H','o','u','r','s',0};
67 static const WCHAR getMinutesW[] = {'g','e','t','M','i','n','u','t','e','s',0};
68 static const WCHAR getUTCMinutesW[] = {'g','e','t','U','T','C','M','i','n','u','t','e','s',0};
69 static const WCHAR getSecondsW[] = {'g','e','t','S','e','c','o','n','d','s',0};
70 static const WCHAR getUTCSecondsW[] = {'g','e','t','U','T','C','S','e','c','o','n','d','s',0};
71 static const WCHAR getMillisecondsW[] = {'g','e','t','M','i','l','l','i','s','e','c','o','n','d','s',0};
72 static const WCHAR getUTCMillisecondsW[] = {'g','e','t','U','T','C','M','i','l','l','i','s','e','c','o','n','d','s',0};
73 static const WCHAR getTimezoneOffsetW[] = {'g','e','t','T','i','m','e','z','o','n','e','O','f','f','s','e','t',0};
74 static const WCHAR setTimeW[] = {'s','e','t','T','i','m','e',0};
75 static const WCHAR setMillisecondsW[] = {'s','e','t','M','i','l','l','i','s','e','c','o','n','d','s',0};
76 static const WCHAR setUTCMillisecondsW[] = {'s','e','t','U','T','C','M','i','l','l','i','s','e','c','o','n','d','s',0};
77 static const WCHAR setSecondsW[] = {'s','e','t','S','e','c','o','n','d','s',0};
78 static const WCHAR setUTCSecondsW[] = {'s','e','t','U','T','C','S','e','c','o','n','d','s',0};
79 static const WCHAR setMinutesW[] = {'s','e','t','M','i','n','u','t','e','s',0};
80 static const WCHAR setUTCMinutesW[] = {'s','e','t','U','T','C','M','i','n','u','t','e','s',0};
81 static const WCHAR setHoursW[] = {'s','e','t','H','o','u','r','s',0};
82 static const WCHAR setUTCHoursW[] = {'s','e','t','U','T','C','H','o','u','r','s',0};
83 static const WCHAR setDateW[] = {'s','e','t','D','a','t','e',0};
84 static const WCHAR setUTCDateW[] = {'s','e','t','U','T','C','D','a','t','e',0};
85 static const WCHAR setMonthW[] = {'s','e','t','M','o','n','t','h',0};
86 static const WCHAR setUTCMonthW[] = {'s','e','t','U','T','C','M','o','n','t','h',0};
87 static const WCHAR setFullYearW[] = {'s','e','t','F','u','l','l','Y','e','a','r',0};
88 static const WCHAR setUTCFullYearW[] = {'s','e','t','U','T','C','F','u','l','l','Y','e','a','r',0};
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
95 /* ECMA-262 3rd Edition    15.9.1.2 */
96 static inline DOUBLE day(DOUBLE time)
97 {
98     return floor(time / MS_PER_DAY);
99 }
100
101 /* ECMA-262 3rd Edition    15.9.1.3 */
102 static inline DOUBLE days_in_year(DOUBLE year)
103 {
104     int y;
105
106     if(year != (int)year)
107         return ret_nan();
108
109     y = year;
110     if(y%4 != 0) return 365;
111     if(y%100 != 0) return 366;
112     if(y%400 != 0) return 365;
113     return 366;
114 }
115
116 /* ECMA-262 3rd Edition    15.9.1.3 */
117 static inline DOUBLE day_from_year(DOUBLE year)
118 {
119     if(year != (int)year)
120         return ret_nan();
121
122     return floor(365.0*(year-1970) + floor((year-1969)/4)
123         - floor((year-1901)/100) + floor((year-1601)/400));
124 }
125
126 static inline int day_from_month(int month, int in_leap_year)
127 {
128     switch(month)
129     {
130         case 0:
131             return 0;
132         case 1:
133             return 31;
134         case 2:
135             return 59+in_leap_year;
136         case 3:
137             return 90+in_leap_year;
138         case 4:
139             return 120+in_leap_year;
140         case 5:
141             return 151+in_leap_year;
142         case 6:
143             return 181+in_leap_year;
144         case 7:
145             return 212+in_leap_year;
146         case 8:
147             return 243+in_leap_year;
148         case 9:
149             return 273+in_leap_year;
150         case 10:
151             return 304+in_leap_year;
152         default:
153             return 334+in_leap_year;
154     }
155 }
156
157 /* ECMA-262 3rd Edition    15.9.1.3 */
158 static inline DOUBLE time_from_year(DOUBLE year)
159 {
160     return MS_PER_DAY*day_from_year(year);
161 }
162
163 /* ECMA-262 3rd Edition    15.9.1.3 */
164 static inline DOUBLE year_from_time(DOUBLE time)
165 {
166     int y;
167
168     if(isnan(time))
169         return ret_nan();
170
171     y = 1970 + time/365.25/MS_PER_DAY;
172
173     if(time_from_year(y) > time)
174         while(time_from_year(y) > time) y--;
175     else
176         while(time_from_year(y+1)<=time) y++;
177
178     return y;
179 }
180
181 /* ECMA-262 3rd Edition    15.9.1.3 */
182 static inline int in_leap_year(DOUBLE time)
183 {
184     if(days_in_year(year_from_time(time))==366)
185         return 1;
186     return 0;
187 }
188
189 /* ECMA-262 3rd Edition    15.9.1.4 */
190 static inline int day_within_year(DOUBLE time)
191 {
192     return day(time) - day_from_year(year_from_time(time));
193 }
194
195 /* ECMA-262 3rd Edition    15.9.1.4 */
196 static inline DOUBLE month_from_time(DOUBLE time)
197 {
198     int ily = in_leap_year(time);
199     int dwy = day_within_year(time);
200
201     if(isnan(time))
202         return ret_nan();
203
204     if(0<=dwy && dwy<31) return 0;
205     if(dwy < 59+ily) return 1;
206     if(dwy < 90+ily) return 2;
207     if(dwy < 120+ily) return 3;
208     if(dwy < 151+ily) return 4;
209     if(dwy < 181+ily) return 5;
210     if(dwy < 212+ily) return 6;
211     if(dwy < 243+ily) return 7;
212     if(dwy < 273+ily) return 8;
213     if(dwy < 304+ily) return  9;
214     if(dwy < 334+ily) return  10;
215     return  11;
216 }
217
218 /* ECMA-262 3rd Edition    15.9.1.5 */
219 static inline DOUBLE date_from_time(DOUBLE time)
220 {
221     int dwy = day_within_year(time);
222     int ily = in_leap_year(time);
223     int mft = month_from_time(time);
224
225     if(isnan(time))
226         return ret_nan();
227
228     if(mft==0) return dwy+1;
229     if(mft==1) return dwy-30;
230     if(mft==2) return dwy-58-ily;
231     if(mft==3) return dwy-89-ily;
232     if(mft==4) return dwy-119-ily;
233     if(mft==5) return dwy-150-ily;
234     if(mft==6) return dwy-180-ily;
235     if(mft==7) return dwy-211-ily;
236     if(mft==8) return dwy-242-ily;
237     if(mft==9) return dwy-272-ily;
238     if(mft==10) return dwy-303-ily;
239     return dwy-333-ily;
240 }
241
242 /* ECMA-262 3rd Edition    15.9.1.6 */
243 static inline DOUBLE week_day(DOUBLE time)
244 {
245     DOUBLE ret;
246
247     if(isnan(time))
248         return ret_nan();
249
250     ret = fmod(day(time)+4, 7);
251     if(ret<0) ret += 7;
252
253     return ret;
254 }
255
256 static inline DOUBLE convert_time(int year, SYSTEMTIME st)
257 {
258     DOUBLE time;
259     int set_week_day;
260
261     if(st.wMonth == 0)
262         return ret_nan();
263
264     if(st.wYear != 0)
265         year = st.wYear;
266
267     time = time_from_year(year);
268     time += (DOUBLE)day_from_month(st.wMonth-1, in_leap_year(time)) * MS_PER_DAY;
269
270     if(st.wYear == 0) {
271         set_week_day = st.wDayOfWeek-week_day(time);
272         if(set_week_day < 0)
273             set_week_day += 7;
274         time += set_week_day * MS_PER_DAY;
275
276         time += (DOUBLE)(st.wDay-1) * 7 * MS_PER_DAY;
277         if(month_from_time(time) != st.wMonth-1)
278             time -= 7 * MS_PER_DAY;
279     }
280     else
281         time += st.wDay * MS_PER_DAY;
282
283     time += st.wHour * MS_PER_HOUR;
284     time += st.wMinute * MS_PER_MINUTE;
285
286     return time;
287 }
288
289 /* ECMA-262 3rd Edition    15.9.1.9 */
290 static inline DOUBLE daylight_saving_ta(DOUBLE time, DateInstance *date)
291 {
292     int year = year_from_time(time);
293     DOUBLE standardTime, daylightTime;
294
295     if(isnan(time))
296         return 0;
297
298     standardTime = convert_time(year, date->standardDate);
299     daylightTime = convert_time(year, date->daylightDate);
300
301     if(isnan(standardTime) || isnan(daylightTime))
302         return 0;
303     else if(standardTime > daylightTime) {
304         if(daylightTime <= time && time < standardTime)
305             return date->daylightBias;
306
307         return date->standardBias;
308     }
309     else {
310         if(standardTime <= time && time < daylightTime)
311             return date->standardBias;
312
313         return date->daylightBias;
314     }
315 }
316
317 /* ECMA-262 3rd Edition    15.9.1.9 */
318 static inline DOUBLE local_time(DOUBLE time, DateInstance *date)
319 {
320     return time - (daylight_saving_ta(time, date)+date->bias)*MS_PER_MINUTE;
321 }
322
323 /* ECMA-262 3rd Edition    15.9.1.9 */
324 static inline DOUBLE utc(DOUBLE time, DateInstance *date)
325 {
326     time += date->bias * MS_PER_MINUTE;
327     return time + daylight_saving_ta(time, date)*MS_PER_MINUTE;
328 }
329
330 /* ECMA-262 3rd Edition    15.9.1.10 */
331 static inline DOUBLE hour_from_time(DOUBLE time)
332 {
333     DOUBLE ret;
334
335     if(isnan(time))
336         return ret_nan();
337
338     ret = fmod(floor(time/MS_PER_HOUR), 24);
339     if(ret<0) ret += 24;
340
341     return ret;
342 }
343
344 /* ECMA-262 3rd Edition    15.9.1.10 */
345 static inline DOUBLE min_from_time(DOUBLE time)
346 {
347     DOUBLE ret;
348
349     if(isnan(time))
350         return ret_nan();
351
352     ret = fmod(floor(time/MS_PER_MINUTE), 60);
353     if(ret<0) ret += 60;
354
355     return ret;
356 }
357
358 /* ECMA-262 3rd Edition    15.9.1.10 */
359 static inline DOUBLE sec_from_time(DOUBLE time)
360 {
361     DOUBLE ret;
362
363     if(isnan(time))
364         return ret_nan();
365
366     ret = fmod(floor(time/1000), 60);
367     if(ret<0) ret += 60;
368
369     return ret;
370 }
371
372 /* ECMA-262 3rd Edition    15.9.1.10 */
373 static inline DOUBLE ms_from_time(DOUBLE time)
374 {
375     DOUBLE ret;
376
377     if(isnan(time))
378         return ret_nan();
379
380     ret = fmod(time, 1000);
381     if(ret<0) ret += 1000;
382
383     return ret;
384 }
385
386 /* ECMA-262 3rd Edition    15.9.1.11 */
387 static inline DOUBLE make_time(DOUBLE hour, DOUBLE min, DOUBLE sec, DOUBLE ms)
388 {
389     return hour*MS_PER_HOUR + min*MS_PER_MINUTE + sec*1000 + ms;
390 }
391
392 /* ECMA-262 3rd Edition    15.9.1.12 */
393 static inline DOUBLE make_day(DOUBLE year, DOUBLE month, DOUBLE day)
394 {
395     DOUBLE time;
396
397     year += floor(month/12);
398
399     month = fmod(month, 12);
400     if(month<0) month += 12;
401
402     time = time_from_year(year);
403
404     day += floor(time / MS_PER_DAY);
405     day += day_from_month(month, in_leap_year(time));
406
407     return day-1;
408 }
409
410 /* ECMA-262 3rd Edition    15.9.1.13 */
411 static inline DOUBLE make_date(DOUBLE day, DOUBLE time)
412 {
413     return day*MS_PER_DAY + time;
414 }
415
416 /* ECMA-262 3rd Edition    15.9.1.14 */
417 static inline DOUBLE time_clip(DOUBLE time)
418 {
419     if(8.64e15 < time || time < -8.64e15) {
420         return ret_nan();
421     }
422
423     return floor(time);
424 }
425
426 static HRESULT Date_toString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
427         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
428 {
429     FIXME("\n");
430     return E_NOTIMPL;
431 }
432
433 static HRESULT Date_toLocaleString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
434         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
435 {
436     FIXME("\n");
437     return E_NOTIMPL;
438 }
439
440 static HRESULT Date_hasOwnProperty(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
441         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
442 {
443     FIXME("\n");
444     return E_NOTIMPL;
445 }
446
447 static HRESULT Date_propertyIsEnumerable(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
448         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
449 {
450     FIXME("\n");
451     return E_NOTIMPL;
452 }
453
454 static HRESULT Date_isPrototypeOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
455         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
456 {
457     FIXME("\n");
458     return E_NOTIMPL;
459 }
460
461 static HRESULT Date_valueOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
462         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
463 {
464     FIXME("\n");
465     return E_NOTIMPL;
466 }
467
468 static HRESULT Date_toUTCString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
469         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
470 {
471     FIXME("\n");
472     return E_NOTIMPL;
473 }
474
475 static HRESULT Date_toDateString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
476         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
477 {
478     FIXME("\n");
479     return E_NOTIMPL;
480 }
481
482 static HRESULT Date_toTimeString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
483         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
484 {
485     FIXME("\n");
486     return E_NOTIMPL;
487 }
488
489 static HRESULT Date_toLocaleDateString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
490         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
491 {
492     FIXME("\n");
493     return E_NOTIMPL;
494 }
495
496 static HRESULT Date_toLocaleTimeString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
497         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
498 {
499     FIXME("\n");
500     return E_NOTIMPL;
501 }
502
503 /* ECMA-262 3rd Edition    15.9.5.9 */
504 static HRESULT Date_getTime(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
505         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
506 {
507     TRACE("\n");
508
509     if(!is_class(dispex, JSCLASS_DATE)) {
510         FIXME("throw TypeError\n");
511         return E_FAIL;
512     }
513
514     if(retv) {
515         DateInstance *date = (DateInstance*)dispex;
516         num_set_val(retv, date->time);
517     }
518     return S_OK;
519 }
520
521 /* ECMA-262 3rd Edition    15.9.5.10 */
522 static HRESULT Date_getFullYear(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
523         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
524 {
525     TRACE("\n");
526
527     if(!is_class(dispex, JSCLASS_DATE)) {
528         FIXME("throw TypeError\n");
529         return E_FAIL;
530     }
531
532     if(retv) {
533         DateInstance *date = (DateInstance*)dispex;
534         DOUBLE time = local_time(date->time, date);
535
536         num_set_val(retv, year_from_time(time));
537     }
538     return S_OK;
539 }
540
541 /* ECMA-262 3rd Edition    15.9.5.11 */
542 static HRESULT Date_getUTCFullYear(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
543         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
544 {
545     TRACE("\n");
546
547     if(!is_class(dispex, JSCLASS_DATE)) {
548         FIXME("throw TypeError\n");
549         return E_FAIL;
550     }
551
552     if(retv) {
553         DateInstance *date = (DateInstance*)dispex;
554         num_set_val(retv, year_from_time(date->time));
555     }
556     return S_OK;
557 }
558
559 /* ECMA-262 3rd Edition    15.9.5.12 */
560 static HRESULT Date_getMonth(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
561         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
562 {
563     TRACE("\n");
564
565     if(!is_class(dispex, JSCLASS_DATE)) {
566         FIXME("throw TypeError\n");
567         return E_FAIL;
568     }
569
570     if(retv) {
571         DateInstance *date = (DateInstance*)dispex;
572         DOUBLE time = local_time(date->time, date);
573
574         num_set_val(retv, month_from_time(time));
575     }
576     return S_OK;
577 }
578
579 /* ECMA-262 3rd Edition    15.9.5.13 */
580 static HRESULT Date_getUTCMonth(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
581         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
582 {
583     TRACE("\n");
584
585     if(!is_class(dispex, JSCLASS_DATE)) {
586         FIXME("throw TypeError\n");
587         return E_FAIL;
588     }
589
590     if(retv) {
591         DateInstance *date = (DateInstance*)dispex;
592         num_set_val(retv, month_from_time(date->time));
593     }
594     return S_OK;
595 }
596
597 /* ECMA-262 3rd Edition    15.9.5.14 */
598 static HRESULT Date_getDate(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
599         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
600 {
601     TRACE("\n");
602
603     if(!is_class(dispex, JSCLASS_DATE)) {
604         FIXME("throw TypeError\n");
605         return E_FAIL;
606     }
607
608     if(retv) {
609         DateInstance *date = (DateInstance*)dispex;
610         DOUBLE time = local_time(date->time, date);
611
612         num_set_val(retv, date_from_time(time));
613     }
614     return S_OK;
615 }
616
617 /* ECMA-262 3rd Edition    15.9.5.15 */
618 static HRESULT Date_getUTCDate(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
619         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
620 {
621     TRACE("\n");
622
623     if(!is_class(dispex, JSCLASS_DATE)) {
624         FIXME("throw TypeError\n");
625         return E_FAIL;
626     }
627
628     if(retv) {
629         DateInstance *date = (DateInstance*)dispex;
630         num_set_val(retv, date_from_time(date->time));
631     }
632     return S_OK;
633 }
634
635 /* ECMA-262 3rd Edition    15.9.5.16 */
636 static HRESULT Date_getDay(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
637         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
638 {
639     TRACE("\n");
640
641     if(!is_class(dispex, JSCLASS_DATE)) {
642         FIXME("throw TypeError\n");
643         return E_FAIL;
644     }
645
646     if(retv) {
647         DateInstance *date = (DateInstance*)dispex;
648         DOUBLE time = local_time(date->time, date);
649
650         num_set_val(retv, week_day(time));
651     }
652     return S_OK;
653 }
654
655 /* ECMA-262 3rd Edition    15.9.5.17 */
656 static HRESULT Date_getUTCDay(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
657         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
658 {
659     TRACE("\n");
660
661     if(!is_class(dispex, JSCLASS_DATE)) {
662         FIXME("throw TypeError\n");
663         return E_FAIL;
664     }
665
666     if(retv) {
667         DateInstance *date = (DateInstance*)dispex;
668         num_set_val(retv, week_day(date->time));
669     }
670     return S_OK;
671 }
672
673 /* ECMA-262 3rd Edition    15.9.5.18 */
674 static HRESULT Date_getHours(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
675         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
676 {
677     TRACE("\n");
678
679     if(!is_class(dispex, JSCLASS_DATE)) {
680         FIXME("throw TypeError\n");
681         return E_FAIL;
682     }
683
684     if(retv) {
685         DateInstance *date = (DateInstance*)dispex;
686         DOUBLE time = local_time(date->time, date);
687
688         num_set_val(retv, hour_from_time(time));
689     }
690     return S_OK;
691 }
692
693 /* ECMA-262 3rd Edition    15.9.5.19 */
694 static HRESULT Date_getUTCHours(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
695         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
696 {
697     TRACE("\n");
698
699     if(!is_class(dispex, JSCLASS_DATE)) {
700         FIXME("throw TypeError\n");
701         return E_FAIL;
702     }
703
704     if(retv) {
705         DateInstance *date = (DateInstance*)dispex;
706         num_set_val(retv, hour_from_time(date->time));
707     }
708     return S_OK;
709 }
710
711 /* ECMA-262 3rd Edition    15.9.5.20 */
712 static HRESULT Date_getMinutes(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
713         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
714 {
715     TRACE("\n");
716
717     if(!is_class(dispex, JSCLASS_DATE)) {
718         FIXME("throw TypeError\n");
719         return E_FAIL;
720     }
721
722     if(retv) {
723         DateInstance *date = (DateInstance*)dispex;
724         DOUBLE time = local_time(date->time, date);
725
726         num_set_val(retv, min_from_time(time));
727     }
728     return S_OK;
729 }
730
731 /* ECMA-262 3rd Edition    15.9.5.21 */
732 static HRESULT Date_getUTCMinutes(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
733         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
734 {
735     TRACE("\n");
736
737     if(!is_class(dispex, JSCLASS_DATE)) {
738         FIXME("throw TypeError\n");
739         return E_FAIL;
740     }
741
742     if(retv) {
743         DateInstance *date = (DateInstance*)dispex;
744         num_set_val(retv, min_from_time(date->time));
745     }
746     return S_OK;
747 }
748
749 /* ECMA-262 3rd Edition    15.9.5.22 */
750 static HRESULT Date_getSeconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
751         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
752 {
753     TRACE("\n");
754
755     if(!is_class(dispex, JSCLASS_DATE)) {
756         FIXME("throw TypeError\n");
757         return E_FAIL;
758     }
759
760     if(retv) {
761         DateInstance *date = (DateInstance*)dispex;
762         DOUBLE time = local_time(date->time, date);
763
764         num_set_val(retv, sec_from_time(time));
765     }
766     return S_OK;
767 }
768
769 /* ECMA-262 3rd Edition    15.9.5.23 */
770 static HRESULT Date_getUTCSeconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
771         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
772 {
773     TRACE("\n");
774
775     if(!is_class(dispex, JSCLASS_DATE)) {
776         FIXME("throw TypeError\n");
777         return E_FAIL;
778     }
779
780     if(retv) {
781         DateInstance *date = (DateInstance*)dispex;
782         num_set_val(retv, sec_from_time(date->time));
783     }
784     return S_OK;
785 }
786
787 /* ECMA-262 3rd Edition    15.9.5.24 */
788 static HRESULT Date_getMilliseconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
789         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
790 {
791     TRACE("\n");
792
793     if(!is_class(dispex, JSCLASS_DATE)) {
794         FIXME("throw TypeError\n");
795         return E_FAIL;
796     }
797
798     if(retv) {
799         DateInstance *date = (DateInstance*)dispex;
800         DOUBLE time = local_time(date->time, date);
801
802         num_set_val(retv, ms_from_time(time));
803     }
804     return S_OK;
805 }
806
807 /* ECMA-262 3rd Edition    15.9.5.25 */
808 static HRESULT Date_getUTCMilliseconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
809         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
810 {
811     TRACE("\n");
812
813     if(!is_class(dispex, JSCLASS_DATE)) {
814         FIXME("throw TypeError\n");
815         return E_FAIL;
816     }
817
818     if(retv) {
819         DateInstance *date = (DateInstance*)dispex;
820         num_set_val(retv, ms_from_time(date->time));
821     }
822     return S_OK;
823 }
824
825 /* ECMA-262 3rd Edition    15.9.5.26 */
826 static HRESULT Date_getTimezoneOffset(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
827         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
828 {
829     TRACE("\n");
830
831     if(!is_class(dispex, JSCLASS_DATE)) {
832         FIXME("throw TypeError\n");
833         return E_FAIL;
834     }
835
836     if(retv) {
837         DateInstance *date = (DateInstance*)dispex;
838         num_set_val(retv, floor(
839                     (date->time-local_time(date->time, date))/MS_PER_MINUTE));
840     }
841     return S_OK;
842 }
843
844 /* ECMA-262 3rd Edition    15.9.5.27 */
845 static HRESULT Date_setTime(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
846         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
847 {
848     VARIANT v;
849     HRESULT hres;
850     DateInstance *date;
851
852     TRACE("\n");
853
854     if(!is_class(dispex, JSCLASS_DATE)) {
855         FIXME("throw TypeError\n");
856         return E_FAIL;
857     }
858
859     if(!arg_cnt(dp)) {
860         FIXME("throw ArgumentNotOptional\n");
861         if(retv) num_set_nan(retv);
862         return S_OK;
863     }
864
865     hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v);
866     if(FAILED(hres))
867         return hres;
868
869     date = (DateInstance*)dispex;
870     date->time = time_clip(num_val(&v));
871
872     if(retv)
873         num_set_val(retv, date->time);
874
875     return S_OK;
876 }
877
878 /* ECMA-262 3rd Edition    15.9.5.28 */
879 static HRESULT Date_setMilliseconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
880         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
881 {
882     VARIANT v;
883     HRESULT hres;
884     DateInstance *date;
885
886     TRACE("\n");
887
888     if(!is_class(dispex, JSCLASS_DATE)) {
889         FIXME("throw TypeError\n");
890         return E_FAIL;
891     }
892
893     if(!arg_cnt(dp)) {
894         FIXME("throw ArgumentNotOptional\n");
895         if(retv) num_set_nan(retv);
896         return S_OK;
897     }
898
899     hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v);
900     if(FAILED(hres))
901         return hres;
902
903     date = (DateInstance*)dispex;
904     date->time = time_clip(date->time - ms_from_time(date->time) + num_val(&v));
905
906     if(retv)
907         num_set_val(retv, date->time);
908
909     return S_OK;
910 }
911
912 /* ECMA-262 3rd Edition    15.9.5.29 */
913 static HRESULT Date_setUTCMilliseconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
914         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
915 {
916     return Date_setMilliseconds(dispex, lcid, flags, dp, retv, ei, caller);
917 }
918
919 /* ECMA-262 3rd Edition    15.9.5.30 */
920 static HRESULT Date_setSeconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
921         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
922 {
923     VARIANT v;
924     HRESULT hres;
925     DateInstance *date;
926
927     TRACE("\n");
928
929     if(!is_class(dispex, JSCLASS_DATE)) {
930         FIXME("throw TypeError\n");
931         return E_FAIL;
932     }
933
934     if(!arg_cnt(dp)) {
935         FIXME("throw ArgumentNotOptional\n");
936         if(retv) num_set_nan(retv);
937         return S_OK;
938     }
939
940     hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v);
941     if(FAILED(hres))
942         return hres;
943
944     date = (DateInstance*)dispex;
945     date->time = time_clip(date->time - (sec_from_time(date->time) - num_val(&v))*1000.0);
946
947     if(retv)
948         num_set_val(retv, date->time);
949
950     return S_OK;
951 }
952
953 /* ECMA-262 3rd Edition    15.9.5.31 */
954 static HRESULT Date_setUTCSeconds(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
955         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
956 {
957     return Date_setSeconds(dispex, lcid, flags, dp, retv, ei, caller);
958 }
959
960 /* ECMA-262 3rd Edition    15.9.5.33 */
961 static HRESULT Date_setMinutes(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
962         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
963 {
964     VARIANT v;
965     HRESULT hres;
966     DateInstance *date;
967
968     TRACE("\n");
969
970     if(!is_class(dispex, JSCLASS_DATE)) {
971         FIXME("throw TypeError\n");
972         return E_FAIL;
973     }
974
975     if(!arg_cnt(dp)) {
976         FIXME("throw ArgumentNotOptional\n");
977         if(retv) num_set_nan(retv);
978         return S_OK;
979     }
980
981     hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v);
982     if(FAILED(hres))
983         return hres;
984
985     date = (DateInstance*)dispex;
986     date->time = time_clip(date->time - (min_from_time(date->time) - num_val(&v))*MS_PER_MINUTE);
987
988     if(retv)
989         num_set_val(retv, date->time);
990
991     return S_OK;
992 }
993
994 /* ECMA-262 3rd Edition    15.9.5.34 */
995 static HRESULT Date_setUTCMinutes(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
996         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
997 {
998     return Date_setMinutes(dispex, lcid, flags, dp, retv, ei, caller);
999 }
1000
1001 /* ECMA-262 3rd Edition    15.9.5.35 */
1002 static HRESULT Date_setHours(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
1003         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
1004 {
1005     VARIANT v;
1006     HRESULT hres;
1007     DateInstance *date;
1008
1009     TRACE("\n");
1010
1011     if(!is_class(dispex, JSCLASS_DATE)) {
1012         FIXME("throw TypeError\n");
1013         return E_FAIL;
1014     }
1015
1016     if(!arg_cnt(dp)) {
1017         FIXME("throw ArgumentNotOptional\n");
1018         if(retv) num_set_nan(retv);
1019         return S_OK;
1020     }
1021
1022     hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v);
1023     if(FAILED(hres))
1024         return hres;
1025
1026     date = (DateInstance*)dispex;
1027     date->time = time_clip(date->time
1028             - (hour_from_time(date->time - date->bias*MS_PER_MINUTE)
1029                 - num_val(&v))*MS_PER_HOUR);
1030
1031     if(retv)
1032         num_set_val(retv, date->time);
1033
1034     return S_OK;
1035 }
1036
1037 /* ECMA-262 3rd Edition    15.9.5.36 */
1038 static HRESULT Date_setUTCHours(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
1039         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
1040 {
1041     VARIANT v;
1042     HRESULT hres;
1043     DateInstance *date;
1044
1045     TRACE("\n");
1046
1047     if(!is_class(dispex, JSCLASS_DATE)) {
1048         FIXME("throw TypeError\n");
1049         return E_FAIL;
1050     }
1051
1052     if(!arg_cnt(dp)) {
1053         FIXME("throw ArgumentNotOptional\n");
1054         if(retv) num_set_nan(retv);
1055         return S_OK;
1056     }
1057
1058     hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &v);
1059     if(FAILED(hres))
1060         return hres;
1061
1062     date = (DateInstance*)dispex;
1063     date->time = time_clip(date->time
1064             - (hour_from_time(date->time) - num_val(&v))*MS_PER_HOUR);
1065
1066     if(retv)
1067         num_set_val(retv, date->time);
1068
1069     return S_OK;
1070 }
1071
1072 /* ECMA-262 3rd Edition    15.9.5.36 */
1073 static HRESULT Date_setDate(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
1074         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
1075 {
1076     FIXME("\n");
1077     return E_NOTIMPL;
1078 }
1079
1080 /* ECMA-262 3rd Edition    15.9.5.37 */
1081 static HRESULT Date_setUTCDate(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
1082         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
1083 {
1084     FIXME("\n");
1085     return E_NOTIMPL;
1086 }
1087
1088 static HRESULT Date_setMonth(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
1089         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
1090 {
1091     FIXME("\n");
1092     return E_NOTIMPL;
1093 }
1094
1095 static HRESULT Date_setUTCMonth(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
1096         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
1097 {
1098     FIXME("\n");
1099     return E_NOTIMPL;
1100 }
1101
1102 static HRESULT Date_setFullYear(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
1103         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
1104 {
1105     FIXME("\n");
1106     return E_NOTIMPL;
1107 }
1108
1109 static HRESULT Date_setUTCFullYear(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
1110         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
1111 {
1112     FIXME("\n");
1113     return E_NOTIMPL;
1114 }
1115
1116 static HRESULT Date_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
1117         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
1118 {
1119     FIXME("\n");
1120     return E_NOTIMPL;
1121 }
1122
1123 static const builtin_prop_t Date_props[] = {
1124     {getDateW,               Date_getDate,               PROPF_METHOD},
1125     {getDayW,                Date_getDay,                PROPF_METHOD},
1126     {getFullYearW,           Date_getFullYear,           PROPF_METHOD},
1127     {getHoursW,              Date_getHours,              PROPF_METHOD},
1128     {getMillisecondsW,       Date_getMilliseconds,       PROPF_METHOD},
1129     {getMinutesW,            Date_getMinutes,            PROPF_METHOD},
1130     {getMonthW,              Date_getMonth,              PROPF_METHOD},
1131     {getSecondsW,            Date_getSeconds,            PROPF_METHOD},
1132     {getTimeW,               Date_getTime,               PROPF_METHOD},
1133     {getTimezoneOffsetW,     Date_getTimezoneOffset,     PROPF_METHOD},
1134     {getUTCDateW,            Date_getUTCDate,            PROPF_METHOD},
1135     {getUTCDayW,             Date_getUTCDay,             PROPF_METHOD},
1136     {getUTCFullYearW,        Date_getUTCFullYear,        PROPF_METHOD},
1137     {getUTCHoursW,           Date_getUTCHours,           PROPF_METHOD},
1138     {getUTCMillisecondsW,    Date_getUTCMilliseconds,    PROPF_METHOD},
1139     {getUTCMinutesW,         Date_getUTCMinutes,         PROPF_METHOD},
1140     {getUTCMonthW,           Date_getUTCMonth,           PROPF_METHOD},
1141     {getUTCSecondsW,         Date_getUTCSeconds,         PROPF_METHOD},
1142     {hasOwnPropertyW,        Date_hasOwnProperty,        PROPF_METHOD},
1143     {isPrototypeOfW,         Date_isPrototypeOf,         PROPF_METHOD},
1144     {propertyIsEnumerableW,  Date_propertyIsEnumerable,  PROPF_METHOD},
1145     {setDateW,               Date_setDate,               PROPF_METHOD},
1146     {setFullYearW,           Date_setFullYear,           PROPF_METHOD},
1147     {setHoursW,              Date_setHours,              PROPF_METHOD},
1148     {setMillisecondsW,       Date_setMilliseconds,       PROPF_METHOD},
1149     {setMinutesW,            Date_setMinutes,            PROPF_METHOD},
1150     {setMonthW,              Date_setMonth,              PROPF_METHOD},
1151     {setSecondsW,            Date_setSeconds,            PROPF_METHOD},
1152     {setTimeW,               Date_setTime,               PROPF_METHOD},
1153     {setUTCDateW,            Date_setUTCDate,            PROPF_METHOD},
1154     {setUTCFullYearW,        Date_setUTCFullYear,        PROPF_METHOD},
1155     {setUTCHoursW,           Date_setUTCHours,           PROPF_METHOD},
1156     {setUTCMillisecondsW,    Date_setUTCMilliseconds,    PROPF_METHOD},
1157     {setUTCMinutesW,         Date_setUTCMinutes,         PROPF_METHOD},
1158     {setUTCMonthW,           Date_setUTCMonth,           PROPF_METHOD},
1159     {setUTCSecondsW,         Date_setUTCSeconds,         PROPF_METHOD},
1160     {toDateStringW,          Date_toDateString,          PROPF_METHOD},
1161     {toLocaleDateStringW,    Date_toLocaleDateString,    PROPF_METHOD},
1162     {toLocaleStringW,        Date_toLocaleString,        PROPF_METHOD},
1163     {toLocaleTimeStringW,    Date_toLocaleTimeString,    PROPF_METHOD},
1164     {toStringW,              Date_toString,              PROPF_METHOD},
1165     {toTimeStringW,          Date_toTimeString,          PROPF_METHOD},
1166     {toUTCStringW,           Date_toUTCString,           PROPF_METHOD},
1167     {valueOfW,               Date_valueOf,               PROPF_METHOD},
1168 };
1169
1170 static const builtin_info_t Date_info = {
1171     JSCLASS_DATE,
1172     {NULL, Date_value, 0},
1173     sizeof(Date_props)/sizeof(*Date_props),
1174     Date_props,
1175     NULL,
1176     NULL
1177 };
1178
1179 static HRESULT create_date(script_ctx_t *ctx, BOOL use_constr, DOUBLE time, DispatchEx **ret)
1180 {
1181     DateInstance *date;
1182     HRESULT hres;
1183     TIME_ZONE_INFORMATION tzi;
1184     DWORD dret;
1185
1186     dret = GetTimeZoneInformation(&tzi);
1187
1188     date = heap_alloc_zero(sizeof(DateInstance));
1189     if(!date)
1190         return E_OUTOFMEMORY;
1191
1192     if(use_constr)
1193         hres = init_dispex_from_constr(&date->dispex, ctx, &Date_info, ctx->date_constr);
1194     else
1195         hres = init_dispex(&date->dispex, ctx, &Date_info, NULL);
1196     if(FAILED(hres)) {
1197         heap_free(date);
1198         return hres;
1199     }
1200
1201     date->time = time;
1202     date->bias = tzi.Bias;
1203     date->standardDate = tzi.StandardDate;
1204     date->standardBias = tzi.StandardBias;
1205     date->daylightDate = tzi.DaylightDate;
1206     date->daylightBias = tzi.DaylightBias;
1207
1208     *ret = &date->dispex;
1209     return S_OK;
1210 }
1211
1212 static HRESULT DateConstr_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
1213         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
1214 {
1215     DispatchEx *date;
1216     HRESULT hres;
1217
1218     TRACE("\n");
1219
1220     switch(flags) {
1221     case DISPATCH_CONSTRUCT:
1222         switch(arg_cnt(dp)) {
1223         /* ECMA-262 3rd Edition    15.9.3.3 */
1224         case 0: {
1225             FILETIME time;
1226             LONGLONG lltime;
1227
1228             GetSystemTimeAsFileTime(&time);
1229             lltime = ((LONGLONG)time.dwHighDateTime<<32)
1230                 + time.dwLowDateTime;
1231
1232             hres = create_date(dispex->ctx, TRUE, lltime/10000-TIME_EPOCH, &date);
1233             if(FAILED(hres))
1234                 return hres;
1235             break;
1236         }
1237
1238         /* ECMA-262 3rd Edition    15.9.3.2 */
1239         case 1: {
1240             VARIANT prim, num;
1241
1242             hres = to_primitive(dispex->ctx, get_arg(dp,0), ei, &prim);
1243             if(FAILED(hres))
1244                 return hres;
1245
1246             if(V_VT(&prim) == VT_BSTR) {
1247                 FIXME("VT_BSTR not supported\n");
1248                 return E_NOTIMPL;
1249             }
1250
1251             hres = to_number(dispex->ctx, &prim, ei, &num);
1252             VariantClear(&prim);
1253             if(FAILED(hres))
1254                 return hres;
1255
1256             hres = create_date(dispex->ctx, TRUE, time_clip(num_val(&num)), &date);
1257             if(FAILED(hres))
1258                 return hres;
1259             break;
1260         }
1261
1262         /* ECMA-262 3rd Edition    15.9.3.1 */
1263         default: {
1264             VARIANT year, month, vdate, hours, minutes, seconds, ms;
1265             DateInstance *di;
1266             int arg_no = arg_cnt(dp), y;
1267
1268             hres = to_number(dispex->ctx, get_arg(dp, 0), ei, &year);
1269             if(FAILED(hres))
1270                 return hres;
1271             y = num_val(&year);
1272             if(0<=y && y<=99)
1273                 y += 1900;
1274
1275
1276             hres = to_number(dispex->ctx, get_arg(dp, 1), ei, &month);
1277             if(FAILED(hres))
1278                 return hres;
1279
1280             if(arg_no>2) {
1281                 hres = to_number(dispex->ctx, get_arg(dp, 2), ei, &vdate);
1282                 if(FAILED(hres))
1283                     return hres;
1284             }
1285             else {
1286                 V_VT(&vdate) = VT_R8;
1287                 V_R8(&vdate) = 1;
1288             }
1289
1290             if(arg_no>3) {
1291                 hres = to_number(dispex->ctx, get_arg(dp, 3), ei, &hours);
1292                 if(FAILED(hres))
1293                     return hres;
1294             }
1295             else {
1296                 V_VT(&hours) = VT_R8;
1297                 V_R8(&hours) = 0;
1298             }
1299
1300             if(arg_no>4) {
1301                 hres = to_number(dispex->ctx, get_arg(dp, 4), ei, &minutes);
1302                 if(FAILED(hres))
1303                     return hres;
1304             }
1305             else {
1306                 V_VT(&minutes) = VT_R8;
1307                 V_R8(&minutes) = 0;
1308             }
1309
1310             if(arg_no>5) {
1311                 hres = to_number(dispex->ctx, get_arg(dp, 5), ei, &seconds);
1312                 if(FAILED(hres))
1313                     return hres;
1314             }
1315             else {
1316                 V_VT(&seconds) = VT_R8;
1317                 V_R8(&seconds) = 0;
1318             }
1319
1320             if(arg_no>6) {
1321                 hres = to_number(dispex->ctx, get_arg(dp, 6), ei, &ms);
1322                 if(FAILED(hres))
1323                     return hres;
1324             }
1325             else {
1326                 V_VT(&ms) = VT_R8;
1327                 V_R8(&ms) = 0;
1328             }
1329
1330             hres = create_date(dispex->ctx, TRUE, time_clip(
1331                         make_date(make_day(y, num_val(&month), num_val(&vdate)),
1332                         make_time(num_val(&hours), num_val(&minutes),
1333                         num_val(&seconds), num_val(&ms)))), &date);
1334             if(FAILED(hres))
1335                 return hres;
1336
1337             di = (DateInstance*)date;
1338             di->time = utc(di->time, di);
1339         }
1340         }
1341
1342         V_VT(retv) = VT_DISPATCH;
1343         V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(date);
1344         return S_OK;
1345
1346     default:
1347         FIXME("unimplemented flags %x\n", flags);
1348         return E_NOTIMPL;
1349     }
1350
1351     return S_OK;
1352 }
1353
1354 HRESULT create_date_constr(script_ctx_t *ctx, DispatchEx **ret)
1355 {
1356     DispatchEx *date;
1357     HRESULT hres;
1358
1359     hres = create_date(ctx, FALSE, 0.0, &date);
1360     if(FAILED(hres))
1361         return hres;
1362
1363     hres = create_builtin_function(ctx, DateConstr_value, PROPF_CONSTR, date, ret);
1364
1365     jsdisp_release(date);
1366     return hres;
1367 }