ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

date.c
Go to the documentation of this file.
00001 /*
00002  * Copyright 2008 Jacek Caban for CodeWeavers
00003  * Copyright 2009 Piotr Caban
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Lesser General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2.1 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public
00016  * License along with this library; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00018  */
00019 
00020 #include "config.h"
00021 #include "wine/port.h"
00022 
00023 #include <limits.h>
00024 #include <math.h>
00025 
00026 #include "jscript.h"
00027 
00028 #include "wine/debug.h"
00029 
00030 WINE_DEFAULT_DEBUG_CHANNEL(jscript);
00031 
00032 /* 1601 to 1970 is 369 years plus 89 leap days */
00033 #define TIME_EPOCH  ((ULONGLONG)(369 * 365 + 89) * 86400 * 1000)
00034 
00035 typedef struct {
00036     DispatchEx dispex;
00037 
00038     /* ECMA-262 3rd Edition    15.9.1.1 */
00039     DOUBLE time;
00040 
00041     LONG bias;
00042     SYSTEMTIME standardDate;
00043     LONG standardBias;
00044     SYSTEMTIME daylightDate;
00045     LONG daylightBias;
00046 } DateInstance;
00047 
00048 static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0};
00049 static const WCHAR toLocaleStringW[] = {'t','o','L','o','c','a','l','e','S','t','r','i','n','g',0};
00050 static const WCHAR propertyIsEnumerableW[] =
00051     {'p','r','o','p','e','r','t','y','I','s','E','n','u','m','e','r','a','b','l','e',0};
00052 static const WCHAR isPrototypeOfW[] = {'i','s','P','r','o','t','o','t','y','p','e','O','f',0};
00053 static const WCHAR valueOfW[] = {'v','a','l','u','e','O','f',0};
00054 static const WCHAR toUTCStringW[] = {'t','o','U','T','C','S','t','r','i','n','g',0};
00055 static const WCHAR toGMTStringW[] = {'t','o','G','M','T','S','t','r','i','n','g',0};
00056 static const WCHAR toDateStringW[] = {'t','o','D','a','t','e','S','t','r','i','n','g',0};
00057 static const WCHAR toTimeStringW[] = {'t','o','T','i','m','e','S','t','r','i','n','g',0};
00058 static const WCHAR toLocaleDateStringW[] = {'t','o','L','o','c','a','l','e','D','a','t','e','S','t','r','i','n','g',0};
00059 static const WCHAR toLocaleTimeStringW[] = {'t','o','L','o','c','a','l','e','T','i','m','e','S','t','r','i','n','g',0};
00060 static const WCHAR getTimeW[] = {'g','e','t','T','i','m','e',0};
00061 static const WCHAR getFullYearW[] = {'g','e','t','F','u','l','l','Y','e','a','r',0};
00062 static const WCHAR getUTCFullYearW[] = {'g','e','t','U','T','C','F','u','l','l','Y','e','a','r',0};
00063 static const WCHAR getMonthW[] = {'g','e','t','M','o','n','t','h',0};
00064 static const WCHAR getUTCMonthW[] = {'g','e','t','U','T','C','M','o','n','t','h',0};
00065 static const WCHAR getDateW[] = {'g','e','t','D','a','t','e',0};
00066 static const WCHAR getUTCDateW[] = {'g','e','t','U','T','C','D','a','t','e',0};
00067 static const WCHAR getDayW[] = {'g','e','t','D','a','y',0};
00068 static const WCHAR getUTCDayW[] = {'g','e','t','U','T','C','D','a','y',0};
00069 static const WCHAR getHoursW[] = {'g','e','t','H','o','u','r','s',0};
00070 static const WCHAR getUTCHoursW[] = {'g','e','t','U','T','C','H','o','u','r','s',0};
00071 static const WCHAR getMinutesW[] = {'g','e','t','M','i','n','u','t','e','s',0};
00072 static const WCHAR getUTCMinutesW[] = {'g','e','t','U','T','C','M','i','n','u','t','e','s',0};
00073 static const WCHAR getSecondsW[] = {'g','e','t','S','e','c','o','n','d','s',0};
00074 static const WCHAR getUTCSecondsW[] = {'g','e','t','U','T','C','S','e','c','o','n','d','s',0};
00075 static const WCHAR getMillisecondsW[] = {'g','e','t','M','i','l','l','i','s','e','c','o','n','d','s',0};
00076 static const WCHAR getUTCMillisecondsW[] = {'g','e','t','U','T','C','M','i','l','l','i','s','e','c','o','n','d','s',0};
00077 static const WCHAR getTimezoneOffsetW[] = {'g','e','t','T','i','m','e','z','o','n','e','O','f','f','s','e','t',0};
00078 static const WCHAR setTimeW[] = {'s','e','t','T','i','m','e',0};
00079 static const WCHAR setMillisecondsW[] = {'s','e','t','M','i','l','l','i','s','e','c','o','n','d','s',0};
00080 static const WCHAR setUTCMillisecondsW[] = {'s','e','t','U','T','C','M','i','l','l','i','s','e','c','o','n','d','s',0};
00081 static const WCHAR setSecondsW[] = {'s','e','t','S','e','c','o','n','d','s',0};
00082 static const WCHAR setUTCSecondsW[] = {'s','e','t','U','T','C','S','e','c','o','n','d','s',0};
00083 static const WCHAR setMinutesW[] = {'s','e','t','M','i','n','u','t','e','s',0};
00084 static const WCHAR setUTCMinutesW[] = {'s','e','t','U','T','C','M','i','n','u','t','e','s',0};
00085 static const WCHAR setHoursW[] = {'s','e','t','H','o','u','r','s',0};
00086 static const WCHAR setUTCHoursW[] = {'s','e','t','U','T','C','H','o','u','r','s',0};
00087 static const WCHAR setDateW[] = {'s','e','t','D','a','t','e',0};
00088 static const WCHAR setUTCDateW[] = {'s','e','t','U','T','C','D','a','t','e',0};
00089 static const WCHAR setMonthW[] = {'s','e','t','M','o','n','t','h',0};
00090 static const WCHAR setUTCMonthW[] = {'s','e','t','U','T','C','M','o','n','t','h',0};
00091 static const WCHAR setFullYearW[] = {'s','e','t','F','u','l','l','Y','e','a','r',0};
00092 static const WCHAR setUTCFullYearW[] = {'s','e','t','U','T','C','F','u','l','l','Y','e','a','r',0};
00093 static const WCHAR getYearW[] = {'g','e','t','Y','e','a','r',0};
00094 
00095 static const WCHAR UTCW[] = {'U','T','C',0};
00096 static const WCHAR parseW[] = {'p','a','r','s','e',0};
00097 
00098 static inline DateInstance *date_this(vdisp_t *jsthis)
00099 {
00100     return is_vclass(jsthis, JSCLASS_DATE) ? (DateInstance*)jsthis->u.jsdisp : NULL;
00101 }
00102 
00103 /*ECMA-262 3rd Edition    15.9.1.2 */
00104 #define MS_PER_DAY 86400000
00105 #define MS_PER_HOUR 3600000
00106 #define MS_PER_MINUTE 60000
00107 
00108 /* ECMA-262 3rd Edition    15.9.1.2 */
00109 static inline DOUBLE day(DOUBLE time)
00110 {
00111     return floor(time / MS_PER_DAY);
00112 }
00113 
00114 /* ECMA-262 3rd Edition    15.9.1.2 */
00115 static inline DOUBLE time_within_day(DOUBLE time)
00116 {
00117     DOUBLE ret;
00118 
00119     ret = fmod(time, MS_PER_DAY);
00120     if(ret < 0)
00121         ret += MS_PER_DAY;
00122 
00123     return ret;
00124 }
00125 
00126 /* ECMA-262 3rd Edition    15.9.1.3 */
00127 static inline DOUBLE days_in_year(DOUBLE year)
00128 {
00129     int y;
00130 
00131     if(year != (int)year)
00132         return ret_nan();
00133 
00134     y = year;
00135     if(y%4 != 0) return 365;
00136     if(y%100 != 0) return 366;
00137     if(y%400 != 0) return 365;
00138     return 366;
00139 }
00140 
00141 /* ECMA-262 3rd Edition    15.9.1.3 */
00142 static inline DOUBLE day_from_year(DOUBLE year)
00143 {
00144     if(year != (int)year)
00145         return ret_nan();
00146 
00147     return floor(365.0*(year-1970) + floor((year-1969)/4)
00148         - floor((year-1901)/100) + floor((year-1601)/400));
00149 }
00150 
00151 static inline int day_from_month(int month, int in_leap_year)
00152 {
00153     switch(month)
00154     {
00155         case 0:
00156             return 0;
00157         case 1:
00158             return 31;
00159         case 2:
00160             return 59+in_leap_year;
00161         case 3:
00162             return 90+in_leap_year;
00163         case 4:
00164             return 120+in_leap_year;
00165         case 5:
00166             return 151+in_leap_year;
00167         case 6:
00168             return 181+in_leap_year;
00169         case 7:
00170             return 212+in_leap_year;
00171         case 8:
00172             return 243+in_leap_year;
00173         case 9:
00174             return 273+in_leap_year;
00175         case 10:
00176             return 304+in_leap_year;
00177         default:
00178             return 334+in_leap_year;
00179     }
00180 }
00181 
00182 /* ECMA-262 3rd Edition    15.9.1.3 */
00183 static inline DOUBLE time_from_year(DOUBLE year)
00184 {
00185     return MS_PER_DAY*day_from_year(year);
00186 }
00187 
00188 /* ECMA-262 3rd Edition    15.9.1.3 */
00189 static inline DOUBLE year_from_time(DOUBLE time)
00190 {
00191     int y;
00192 
00193     if(isnan(time))
00194         return ret_nan();
00195 
00196     y = 1970 + time/365.25/MS_PER_DAY;
00197 
00198     if(time_from_year(y) > time)
00199         while(time_from_year(y) > time) y--;
00200     else
00201         while(time_from_year(y+1)<=time) y++;
00202 
00203     return y;
00204 }
00205 
00206 /* ECMA-262 3rd Edition    15.9.1.3 */
00207 static inline int in_leap_year(DOUBLE time)
00208 {
00209     if(days_in_year(year_from_time(time))==366)
00210         return 1;
00211     return 0;
00212 }
00213 
00214 /* ECMA-262 3rd Edition    15.9.1.4 */
00215 static inline int day_within_year(DOUBLE time)
00216 {
00217     return day(time) - day_from_year(year_from_time(time));
00218 }
00219 
00220 /* ECMA-262 3rd Edition    15.9.1.4 */
00221 static inline DOUBLE month_from_time(DOUBLE time)
00222 {
00223     int ily = in_leap_year(time);
00224     int dwy = day_within_year(time);
00225 
00226     if(isnan(time))
00227         return ret_nan();
00228 
00229     if(0<=dwy && dwy<31) return 0;
00230     if(dwy < 59+ily) return 1;
00231     if(dwy < 90+ily) return 2;
00232     if(dwy < 120+ily) return 3;
00233     if(dwy < 151+ily) return 4;
00234     if(dwy < 181+ily) return 5;
00235     if(dwy < 212+ily) return 6;
00236     if(dwy < 243+ily) return 7;
00237     if(dwy < 273+ily) return 8;
00238     if(dwy < 304+ily) return  9;
00239     if(dwy < 334+ily) return  10;
00240     return  11;
00241 }
00242 
00243 /* ECMA-262 3rd Edition    15.9.1.5 */
00244 static inline DOUBLE date_from_time(DOUBLE time)
00245 {
00246     int dwy = day_within_year(time);
00247     int ily = in_leap_year(time);
00248     int mft = month_from_time(time);
00249 
00250     if(isnan(time))
00251         return ret_nan();
00252 
00253     if(mft==0) return dwy+1;
00254     if(mft==1) return dwy-30;
00255     if(mft==2) return dwy-58-ily;
00256     if(mft==3) return dwy-89-ily;
00257     if(mft==4) return dwy-119-ily;
00258     if(mft==5) return dwy-150-ily;
00259     if(mft==6) return dwy-180-ily;
00260     if(mft==7) return dwy-211-ily;
00261     if(mft==8) return dwy-242-ily;
00262     if(mft==9) return dwy-272-ily;
00263     if(mft==10) return dwy-303-ily;
00264     return dwy-333-ily;
00265 }
00266 
00267 /* ECMA-262 3rd Edition    15.9.1.6 */
00268 static inline DOUBLE week_day(DOUBLE time)
00269 {
00270     DOUBLE ret;
00271 
00272     if(isnan(time))
00273         return ret_nan();
00274 
00275     ret = fmod(day(time)+4, 7);
00276     if(ret<0) ret += 7;
00277 
00278     return ret;
00279 }
00280 
00281 static inline DOUBLE convert_time(int year, SYSTEMTIME st)
00282 {
00283     DOUBLE time;
00284     int set_week_day;
00285 
00286     if(st.wMonth == 0)
00287         return ret_nan();
00288 
00289     if(st.wYear != 0)
00290         year = st.wYear;
00291 
00292     time = time_from_year(year);
00293     time += (DOUBLE)day_from_month(st.wMonth-1, in_leap_year(time)) * MS_PER_DAY;
00294 
00295     if(st.wYear == 0) {
00296         set_week_day = st.wDayOfWeek-week_day(time);
00297         if(set_week_day < 0)
00298             set_week_day += 7;
00299         time += set_week_day * MS_PER_DAY;
00300 
00301         time += (DOUBLE)(st.wDay-1) * 7 * MS_PER_DAY;
00302         if(month_from_time(time) != st.wMonth-1)
00303             time -= 7 * MS_PER_DAY;
00304     }
00305     else
00306         time += st.wDay * MS_PER_DAY;
00307 
00308     time += st.wHour * MS_PER_HOUR;
00309     time += st.wMinute * MS_PER_MINUTE;
00310 
00311     return time;
00312 }
00313 
00314 /* ECMA-262 3rd Edition    15.9.1.9 */
00315 static inline DOUBLE daylight_saving_ta(DOUBLE time, DateInstance *date)
00316 {
00317     int year = year_from_time(time);
00318     DOUBLE standardTime, daylightTime;
00319 
00320     if(isnan(time))
00321         return 0;
00322 
00323     standardTime = convert_time(year, date->standardDate);
00324     daylightTime = convert_time(year, date->daylightDate);
00325 
00326     if(isnan(standardTime) || isnan(daylightTime))
00327         return 0;
00328     else if(standardTime > daylightTime) {
00329         if(daylightTime <= time && time < standardTime)
00330             return date->daylightBias;
00331 
00332         return date->standardBias;
00333     }
00334     else {
00335         if(standardTime <= time && time < daylightTime)
00336             return date->standardBias;
00337 
00338         return date->daylightBias;
00339     }
00340 }
00341 
00342 /* ECMA-262 3rd Edition    15.9.1.9 */
00343 static inline DOUBLE local_time(DOUBLE time, DateInstance *date)
00344 {
00345     return time - (daylight_saving_ta(time, date)+date->bias)*MS_PER_MINUTE;
00346 }
00347 
00348 /* ECMA-262 3rd Edition    15.9.1.9 */
00349 static inline DOUBLE utc(DOUBLE time, DateInstance *date)
00350 {
00351     time += date->bias * MS_PER_MINUTE;
00352     return time + daylight_saving_ta(time, date)*MS_PER_MINUTE;
00353 }
00354 
00355 /* ECMA-262 3rd Edition    15.9.1.10 */
00356 static inline DOUBLE hour_from_time(DOUBLE time)
00357 {
00358     DOUBLE ret;
00359 
00360     if(isnan(time))
00361         return ret_nan();
00362 
00363     ret = fmod(floor(time/MS_PER_HOUR), 24);
00364     if(ret<0) ret += 24;
00365 
00366     return ret;
00367 }
00368 
00369 /* ECMA-262 3rd Edition    15.9.1.10 */
00370 static inline DOUBLE min_from_time(DOUBLE time)
00371 {
00372     DOUBLE ret;
00373 
00374     if(isnan(time))
00375         return ret_nan();
00376 
00377     ret = fmod(floor(time/MS_PER_MINUTE), 60);
00378     if(ret<0) ret += 60;
00379 
00380     return ret;
00381 }
00382 
00383 /* ECMA-262 3rd Edition    15.9.1.10 */
00384 static inline DOUBLE sec_from_time(DOUBLE time)
00385 {
00386     DOUBLE ret;
00387 
00388     if(isnan(time))
00389         return ret_nan();
00390 
00391     ret = fmod(floor(time/1000), 60);
00392     if(ret<0) ret += 60;
00393 
00394     return ret;
00395 }
00396 
00397 /* ECMA-262 3rd Edition    15.9.1.10 */
00398 static inline DOUBLE ms_from_time(DOUBLE time)
00399 {
00400     DOUBLE ret;
00401 
00402     if(isnan(time))
00403         return ret_nan();
00404 
00405     ret = fmod(time, 1000);
00406     if(ret<0) ret += 1000;
00407 
00408     return ret;
00409 }
00410 
00411 /* ECMA-262 3rd Edition    15.9.1.11 */
00412 static inline DOUBLE make_time(DOUBLE hour, DOUBLE min, DOUBLE sec, DOUBLE ms)
00413 {
00414     return hour*MS_PER_HOUR + min*MS_PER_MINUTE + sec*1000 + ms;
00415 }
00416 
00417 /* ECMA-262 3rd Edition    15.9.1.12 */
00418 static inline DOUBLE make_day(DOUBLE year, DOUBLE month, DOUBLE day)
00419 {
00420     DOUBLE time;
00421 
00422     year += floor(month/12);
00423 
00424     month = fmod(month, 12);
00425     if(month<0) month += 12;
00426 
00427     time = time_from_year(year);
00428 
00429     day += floor(time / MS_PER_DAY);
00430     day += day_from_month(month, in_leap_year(time));
00431 
00432     return day-1;
00433 }
00434 
00435 /* ECMA-262 3rd Edition    15.9.1.13 */
00436 static inline DOUBLE make_date(DOUBLE day, DOUBLE time)
00437 {
00438     return day*MS_PER_DAY + time;
00439 }
00440 
00441 /* ECMA-262 3rd Edition    15.9.1.14 */
00442 static inline DOUBLE time_clip(DOUBLE time)
00443 {
00444     if(8.64e15 < time || time < -8.64e15) {
00445         return ret_nan();
00446     }
00447 
00448     return floor(time);
00449 }
00450 
00451 static SYSTEMTIME create_systemtime(DOUBLE time)
00452 {
00453     SYSTEMTIME st;
00454 
00455     st.wYear = year_from_time(time);
00456     st.wMonth = month_from_time(time) + 1;
00457     st.wDayOfWeek = week_day(time);
00458     st.wDay = date_from_time(time);
00459     st.wHour = hour_from_time(time);
00460     st.wMinute = min_from_time(time);
00461     st.wSecond = sec_from_time(time);
00462     st.wMilliseconds = ms_from_time(time);
00463 
00464     return st;
00465 }
00466 
00467 static inline HRESULT date_to_string(DOUBLE time, BOOL show_offset, int offset, VARIANT *retv)
00468 {
00469     static const WCHAR NaNW[] = { 'N','a','N',0 };
00470     static const WCHAR formatW[] = { '%','s',' ','%','s',' ','%','d',' ',
00471         '%','0','2','d',':','%','0','2','d',':','%','0','2','d',' ',
00472         'U','T','C','%','c','%','0','2','d','%','0','2','d',' ','%','d','%','s',0 };
00473     static const WCHAR formatUTCW[] = { '%','s',' ','%','s',' ','%','d',' ',
00474         '%','0','2','d',':','%','0','2','d',':','%','0','2','d',' ',
00475         'U','T','C',' ','%','d','%','s',0 };
00476     static const WCHAR formatNoOffsetW[] = { '%','s',' ','%','s',' ',
00477         '%','d',' ','%','0','2','d',':','%','0','2','d',':',
00478         '%','0','2','d',' ','%','d','%','s',0 };
00479     static const WCHAR ADW[] = { 0 };
00480     static const WCHAR BCW[] = { ' ','B','.','C','.',0 };
00481 
00482     static const DWORD week_ids[] = { LOCALE_SABBREVDAYNAME7, LOCALE_SABBREVDAYNAME1,
00483         LOCALE_SABBREVDAYNAME2, LOCALE_SABBREVDAYNAME3, LOCALE_SABBREVDAYNAME4,
00484         LOCALE_SABBREVDAYNAME5, LOCALE_SABBREVDAYNAME6 };
00485     static const DWORD month_ids[] = { LOCALE_SABBREVMONTHNAME1, LOCALE_SABBREVMONTHNAME2,
00486         LOCALE_SABBREVMONTHNAME3, LOCALE_SABBREVMONTHNAME4,
00487         LOCALE_SABBREVMONTHNAME5, LOCALE_SABBREVMONTHNAME6,
00488         LOCALE_SABBREVMONTHNAME7, LOCALE_SABBREVMONTHNAME8,
00489         LOCALE_SABBREVMONTHNAME9, LOCALE_SABBREVMONTHNAME10,
00490         LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12 };
00491 
00492     BOOL formatAD = TRUE;
00493     BSTR week, month;
00494     BSTR date_str;
00495     int len, size, year, day;
00496     DWORD lcid_en, week_id, month_id;
00497     WCHAR sign = '-';
00498 
00499     if(isnan(time)) {
00500         if(retv) {
00501             V_VT(retv) = VT_BSTR;
00502             V_BSTR(retv) = SysAllocString(NaNW);
00503             if(!V_BSTR(retv))
00504                 return E_OUTOFMEMORY;
00505         }
00506         return S_OK;
00507     }
00508 
00509     if(retv) {
00510         len = 21;
00511 
00512         lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT);
00513 
00514         week_id = week_ids[(int)week_day(time)];
00515         size = GetLocaleInfoW(lcid_en, week_id, NULL, 0);
00516         week = SysAllocStringLen(NULL, size);
00517         if(!week)
00518             return E_OUTOFMEMORY;
00519         GetLocaleInfoW(lcid_en, week_id, week, size);
00520         len += size-1;
00521 
00522         month_id = month_ids[(int)month_from_time(time)];
00523         size = GetLocaleInfoW(lcid_en, month_id, NULL, 0);
00524         month = SysAllocStringLen(NULL, size);
00525         if(!month) {
00526             SysFreeString(week);
00527             return E_OUTOFMEMORY;
00528         }
00529         GetLocaleInfoW(lcid_en, month_id, month, size);
00530         len += size-1;
00531 
00532         year = year_from_time(time);
00533         if(year<0)
00534             year = -year+1;
00535         do {
00536             year /= 10;
00537             len++;
00538         } while(year);
00539 
00540         year = year_from_time(time);
00541         if(year<0) {
00542             formatAD = FALSE;
00543             year = -year+1;
00544             len += 5;
00545         }
00546 
00547         day = date_from_time(time);
00548         do {
00549             day /= 10;
00550             len++;
00551         } while(day);
00552         day = date_from_time(time);
00553 
00554         if(!show_offset) len -= 9;
00555         else if(offset == 0) len -= 5;
00556         else if(offset < 0) {
00557             sign = '+';
00558             offset = -offset;
00559         }
00560 
00561         date_str = SysAllocStringLen(NULL, len);
00562         if(!date_str) {
00563             SysFreeString(week);
00564             SysFreeString(month);
00565             return E_OUTOFMEMORY;
00566         }
00567 
00568         if(!show_offset)
00569             sprintfW(date_str, formatNoOffsetW, week, month, day,
00570                     (int)hour_from_time(time), (int)min_from_time(time),
00571                     (int)sec_from_time(time), year, formatAD?ADW:BCW);
00572         else if(offset)
00573             sprintfW(date_str, formatW, week, month, day,
00574                     (int)hour_from_time(time), (int)min_from_time(time),
00575                     (int)sec_from_time(time), sign, offset/60, offset%60,
00576                     year, formatAD?ADW:BCW);
00577         else
00578             sprintfW(date_str, formatUTCW, week, month, day,
00579                     (int)hour_from_time(time), (int)min_from_time(time),
00580                     (int)sec_from_time(time), year, formatAD?ADW:BCW);
00581 
00582         SysFreeString(week);
00583         SysFreeString(month);
00584 
00585         V_VT(retv) = VT_BSTR;
00586         V_BSTR(retv) = date_str;
00587     }
00588     return S_OK;
00589 }
00590 
00591 /* ECMA-262 3rd Edition    15.9.1.2 */
00592 static HRESULT dateobj_to_string(DateInstance *date, VARIANT *retv)
00593 {
00594     DOUBLE time;
00595     int offset;
00596 
00597     time = local_time(date->time, date);
00598     offset = date->bias +
00599         daylight_saving_ta(time, date);
00600 
00601     return date_to_string(time, TRUE, offset, retv);
00602 }
00603 
00604 static HRESULT Date_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00605         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
00606 {
00607     DateInstance *date;
00608 
00609     TRACE("\n");
00610 
00611     if(!(date = date_this(jsthis)))
00612         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
00613 
00614     return dateobj_to_string(date, retv);
00615 }
00616 
00617 /* ECMA-262 3rd Edition    15.9.1.5 */
00618 static HRESULT Date_toLocaleString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00619         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
00620 {
00621     static const WCHAR NaNW[] = { 'N','a','N',0 };
00622     SYSTEMTIME st;
00623     DateInstance *date;
00624     BSTR date_str;
00625     int date_len, time_len;
00626 
00627     TRACE("\n");
00628 
00629     if(!(date = date_this(jsthis)))
00630         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
00631 
00632     if(isnan(date->time)) {
00633         if(retv) {
00634             V_VT(retv) = VT_BSTR;
00635             V_BSTR(retv) = SysAllocString(NaNW);
00636             if(!V_BSTR(retv))
00637                 return E_OUTOFMEMORY;
00638         }
00639         return S_OK;
00640     }
00641 
00642     st = create_systemtime(local_time(date->time, date));
00643 
00644     if(st.wYear<1601 || st.wYear>9999)
00645         return dateobj_to_string(date, retv);
00646 
00647     if(retv) {
00648         date_len = GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, NULL, 0);
00649         time_len = GetTimeFormatW(ctx->lcid, 0, &st, NULL, NULL, 0);
00650         date_str = SysAllocStringLen(NULL, date_len+time_len-1);
00651         if(!date_str)
00652             return E_OUTOFMEMORY;
00653         GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, date_str, date_len);
00654         GetTimeFormatW(ctx->lcid, 0, &st, NULL, &date_str[date_len], time_len);
00655         date_str[date_len-1] = ' ';
00656 
00657         V_VT(retv) = VT_BSTR;
00658         V_BSTR(retv) = date_str;
00659     }
00660     return S_OK;
00661 }
00662 
00663 static HRESULT Date_valueOf(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00664         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
00665 {
00666     DateInstance *date;
00667 
00668     TRACE("\n");
00669 
00670     if(!(date = date_this(jsthis)))
00671         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
00672 
00673     if(retv)
00674         num_set_val(retv, date->time);
00675     return S_OK;
00676 }
00677 
00678 static inline HRESULT create_utc_string(script_ctx_t *ctx, vdisp_t *jsthis,
00679         VARIANT *retv, jsexcept_t *ei)
00680 {
00681     static const WCHAR NaNW[] = { 'N','a','N',0 };
00682     static const WCHAR formatADW[] = { '%','s',',',' ','%','d',' ','%','s',' ','%','d',' ',
00683         '%','0','2','d',':','%','0','2','d',':','%','0','2','d',' ','U','T','C',0 };
00684     static const WCHAR formatBCW[] = { '%','s',',',' ','%','d',' ','%','s',' ','%','d',' ','B','.','C','.',' ',
00685         '%','0','2','d',':','%','0','2','d',':','%','0','2','d',' ','U','T','C',0 };
00686 
00687     static const DWORD week_ids[] = { LOCALE_SABBREVDAYNAME7, LOCALE_SABBREVDAYNAME1,
00688         LOCALE_SABBREVDAYNAME2, LOCALE_SABBREVDAYNAME3, LOCALE_SABBREVDAYNAME4,
00689         LOCALE_SABBREVDAYNAME5, LOCALE_SABBREVDAYNAME6 };
00690     static const DWORD month_ids[] = { LOCALE_SABBREVMONTHNAME1, LOCALE_SABBREVMONTHNAME2,
00691         LOCALE_SABBREVMONTHNAME3, LOCALE_SABBREVMONTHNAME4,
00692         LOCALE_SABBREVMONTHNAME5, LOCALE_SABBREVMONTHNAME6,
00693         LOCALE_SABBREVMONTHNAME7, LOCALE_SABBREVMONTHNAME8,
00694         LOCALE_SABBREVMONTHNAME9, LOCALE_SABBREVMONTHNAME10,
00695         LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12 };
00696 
00697     BOOL formatAD = TRUE;
00698     BSTR week, month;
00699     DateInstance *date;
00700     BSTR date_str;
00701     int len, size, year, day;
00702     DWORD lcid_en, week_id, month_id;
00703 
00704     if(!(date = date_this(jsthis)))
00705         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
00706 
00707     if(isnan(date->time)) {
00708         if(retv) {
00709             V_VT(retv) = VT_BSTR;
00710             V_BSTR(retv) = SysAllocString(NaNW);
00711             if(!V_BSTR(retv))
00712                 return E_OUTOFMEMORY;
00713         }
00714         return S_OK;
00715     }
00716 
00717     if(retv) {
00718         len = 17;
00719 
00720         lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT);
00721 
00722         week_id = week_ids[(int)week_day(date->time)];
00723         size = GetLocaleInfoW(lcid_en, week_id, NULL, 0);
00724         week = SysAllocStringLen(NULL, size);
00725         if(!week)
00726             return E_OUTOFMEMORY;
00727         GetLocaleInfoW(lcid_en, week_id, week, size);
00728         len += size-1;
00729 
00730         month_id = month_ids[(int)month_from_time(date->time)];
00731         size = GetLocaleInfoW(lcid_en, month_id, NULL, 0);
00732         month = SysAllocStringLen(NULL, size);
00733         if(!month) {
00734             SysFreeString(week);
00735             return E_OUTOFMEMORY;
00736         }
00737         GetLocaleInfoW(lcid_en, month_id, month, size);
00738         len += size-1;
00739 
00740         year = year_from_time(date->time);
00741         if(year<0)
00742             year = -year+1;
00743         do {
00744             year /= 10;
00745             len++;
00746         } while(year);
00747 
00748         year = year_from_time(date->time);
00749         if(year<0) {
00750             formatAD = FALSE;
00751             year = -year+1;
00752             len += 5;
00753         }
00754 
00755         day = date_from_time(date->time);
00756         do {
00757             day /= 10;
00758             len++;
00759         } while(day);
00760         day = date_from_time(date->time);
00761 
00762         date_str = SysAllocStringLen(NULL, len);
00763         if(!date_str) {
00764             SysFreeString(week);
00765             SysFreeString(month);
00766             return E_OUTOFMEMORY;
00767         }
00768         sprintfW(date_str, formatAD?formatADW:formatBCW, week, day, month, year,
00769                 (int)hour_from_time(date->time), (int)min_from_time(date->time),
00770                 (int)sec_from_time(date->time));
00771 
00772         SysFreeString(week);
00773         SysFreeString(month);
00774 
00775         V_VT(retv) = VT_BSTR;
00776         V_BSTR(retv) = date_str;
00777     }
00778     return S_OK;
00779 }
00780 
00781 /* ECMA-262 3rd Edition    15.9.5.42 */
00782 static HRESULT Date_toUTCString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00783         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
00784 {
00785     TRACE("\n");
00786     return create_utc_string(ctx, jsthis, retv, ei);
00787 }
00788 
00789 static HRESULT Date_toGMTString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00790         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
00791 {
00792     TRACE("\n");
00793     return create_utc_string(ctx, jsthis, retv, ei);
00794 }
00795 
00796 /* ECMA-262 3rd Edition    15.9.5.3 */
00797 static HRESULT dateobj_to_date_string(DateInstance *date, VARIANT *retv)
00798 {
00799     static const WCHAR NaNW[] = { 'N','a','N',0 };
00800     static const WCHAR formatADW[] = { '%','s',' ','%','s',' ','%','d',' ','%','d',0 };
00801     static const WCHAR formatBCW[] = { '%','s',' ','%','s',' ','%','d',' ','%','d',' ','B','.','C','.',0 };
00802 
00803     static const DWORD week_ids[] = { LOCALE_SABBREVDAYNAME7, LOCALE_SABBREVDAYNAME1,
00804         LOCALE_SABBREVDAYNAME2, LOCALE_SABBREVDAYNAME3, LOCALE_SABBREVDAYNAME4,
00805         LOCALE_SABBREVDAYNAME5, LOCALE_SABBREVDAYNAME6 };
00806     static const DWORD month_ids[] = { LOCALE_SABBREVMONTHNAME1, LOCALE_SABBREVMONTHNAME2,
00807         LOCALE_SABBREVMONTHNAME3, LOCALE_SABBREVMONTHNAME4,
00808         LOCALE_SABBREVMONTHNAME5, LOCALE_SABBREVMONTHNAME6,
00809         LOCALE_SABBREVMONTHNAME7, LOCALE_SABBREVMONTHNAME8,
00810         LOCALE_SABBREVMONTHNAME9, LOCALE_SABBREVMONTHNAME10,
00811         LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12 };
00812 
00813     BOOL formatAD = TRUE;
00814     BSTR week, month;
00815     BSTR date_str;
00816     DOUBLE time;
00817     int len, size, year, day;
00818     DWORD lcid_en, week_id, month_id;
00819 
00820     if(isnan(date->time)) {
00821         if(retv) {
00822             V_VT(retv) = VT_BSTR;
00823             V_BSTR(retv) = SysAllocString(NaNW);
00824             if(!V_BSTR(retv))
00825                 return E_OUTOFMEMORY;
00826         }
00827         return S_OK;
00828     }
00829 
00830     time = local_time(date->time, date);
00831 
00832     if(retv) {
00833         len = 5;
00834 
00835         lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT);
00836 
00837         week_id = week_ids[(int)week_day(time)];
00838         size = GetLocaleInfoW(lcid_en, week_id, NULL, 0);
00839         week = SysAllocStringLen(NULL, size);
00840         if(!week)
00841             return E_OUTOFMEMORY;
00842         GetLocaleInfoW(lcid_en, week_id, week, size);
00843         len += size-1;
00844 
00845         month_id = month_ids[(int)month_from_time(time)];
00846         size = GetLocaleInfoW(lcid_en, month_id, NULL, 0);
00847         month = SysAllocStringLen(NULL, size);
00848         if(!month) {
00849             SysFreeString(week);
00850             return E_OUTOFMEMORY;
00851         }
00852         GetLocaleInfoW(lcid_en, month_id, month, size);
00853         len += size-1;
00854 
00855         year = year_from_time(time);
00856         if(year<0)
00857             year = -year+1;
00858         do {
00859             year /= 10;
00860             len++;
00861         } while(year);
00862 
00863         year = year_from_time(time);
00864         if(year<0) {
00865             formatAD = FALSE;
00866             year = -year+1;
00867             len += 5;
00868         }
00869 
00870         day = date_from_time(time);
00871         do {
00872             day /= 10;
00873             len++;
00874         } while(day);
00875         day = date_from_time(time);
00876 
00877         date_str = SysAllocStringLen(NULL, len);
00878         if(!date_str) {
00879             SysFreeString(week);
00880             SysFreeString(month);
00881             return E_OUTOFMEMORY;
00882         }
00883         sprintfW(date_str, formatAD?formatADW:formatBCW, week, month, day, year);
00884 
00885         SysFreeString(week);
00886         SysFreeString(month);
00887 
00888         V_VT(retv) = VT_BSTR;
00889         V_BSTR(retv) = date_str;
00890     }
00891     return S_OK;
00892 }
00893 
00894 static HRESULT Date_toDateString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00895         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
00896 {
00897     DateInstance *date;
00898 
00899     if(!(date = date_this(jsthis)))
00900         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
00901 
00902     return dateobj_to_date_string(date, retv);
00903 }
00904 
00905 /* ECMA-262 3rd Edition    15.9.5.4 */
00906 static HRESULT Date_toTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00907         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
00908 {
00909     static const WCHAR NaNW[] = { 'N','a','N',0 };
00910     static const WCHAR formatW[] = { '%','0','2','d',':','%','0','2','d',':','%','0','2','d',
00911         ' ','U','T','C','%','c','%','0','2','d','%','0','2','d',0 };
00912     static const WCHAR formatUTCW[] = { '%','0','2','d',':','%','0','2','d',
00913         ':','%','0','2','d',' ','U','T','C',0 };
00914     DateInstance *date;
00915     BSTR date_str;
00916     DOUBLE time;
00917     WCHAR sign;
00918     int offset;
00919 
00920     TRACE("\n");
00921 
00922     if(!(date = date_this(jsthis)))
00923         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
00924 
00925     if(isnan(date->time)) {
00926         if(retv) {
00927             V_VT(retv) = VT_BSTR;
00928             V_BSTR(retv) = SysAllocString(NaNW);
00929             if(!V_BSTR(retv))
00930                 return E_OUTOFMEMORY;
00931         }
00932         return S_OK;
00933     }
00934 
00935     time = local_time(date->time, date);
00936 
00937     if(retv) {
00938         date_str = SysAllocStringLen(NULL, 17);
00939         if(!date_str)
00940             return E_OUTOFMEMORY;
00941 
00942         offset = date->bias +
00943             daylight_saving_ta(time, date);
00944 
00945         if(offset < 0) {
00946             sign = '+';
00947             offset = -offset;
00948         }
00949         else sign = '-';
00950 
00951         if(offset)
00952             sprintfW(date_str, formatW, (int)hour_from_time(time),
00953                     (int)min_from_time(time), (int)sec_from_time(time),
00954                     sign, offset/60, offset%60);
00955         else
00956             sprintfW(date_str, formatUTCW, (int)hour_from_time(time),
00957                     (int)min_from_time(time), (int)sec_from_time(time));
00958 
00959         V_VT(retv) = VT_BSTR;
00960         V_BSTR(retv) = date_str;
00961     }
00962     return S_OK;
00963 }
00964 
00965 /* ECMA-262 3rd Edition    15.9.5.6 */
00966 static HRESULT Date_toLocaleDateString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
00967         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
00968 {
00969     static const WCHAR NaNW[] = { 'N','a','N',0 };
00970     SYSTEMTIME st;
00971     DateInstance *date;
00972     BSTR date_str;
00973     int len;
00974 
00975     TRACE("\n");
00976 
00977     if(!(date = date_this(jsthis)))
00978         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
00979 
00980     if(isnan(date->time)) {
00981         if(retv) {
00982             V_VT(retv) = VT_BSTR;
00983             V_BSTR(retv) = SysAllocString(NaNW);
00984             if(!V_BSTR(retv))
00985                 return E_OUTOFMEMORY;
00986         }
00987         return S_OK;
00988     }
00989 
00990     st = create_systemtime(local_time(date->time, date));
00991 
00992     if(st.wYear<1601 || st.wYear>9999)
00993         return dateobj_to_date_string(date, retv);
00994 
00995     if(retv) {
00996         len = GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, NULL, 0);
00997         date_str = SysAllocStringLen(NULL, len);
00998         if(!date_str)
00999             return E_OUTOFMEMORY;
01000         GetDateFormatW(ctx->lcid, DATE_LONGDATE, &st, NULL, date_str, len);
01001 
01002         V_VT(retv) = VT_BSTR;
01003         V_BSTR(retv) = date_str;
01004     }
01005     return S_OK;
01006 }
01007 
01008 /* ECMA-262 3rd Edition    15.9.5.7 */
01009 static HRESULT Date_toLocaleTimeString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01010         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01011 {
01012     static const WCHAR NaNW[] = { 'N','a','N',0 };
01013     SYSTEMTIME st;
01014     DateInstance *date;
01015     BSTR date_str;
01016     int len;
01017 
01018     TRACE("\n");
01019 
01020     if(!(date = date_this(jsthis)))
01021         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01022 
01023     if(isnan(date->time)) {
01024         if(retv) {
01025             V_VT(retv) = VT_BSTR;
01026             V_BSTR(retv) = SysAllocString(NaNW);
01027             if(!V_BSTR(retv))
01028                 return E_OUTOFMEMORY;
01029         }
01030         return S_OK;
01031     }
01032 
01033     st = create_systemtime(local_time(date->time, date));
01034 
01035     if(st.wYear<1601 || st.wYear>9999)
01036         return Date_toTimeString(ctx, jsthis, flags, dp, retv, ei, caller);
01037 
01038     if(retv) {
01039         len = GetTimeFormatW(ctx->lcid, 0, &st, NULL, NULL, 0);
01040         date_str = SysAllocStringLen(NULL, len);
01041         if(!date_str)
01042             return E_OUTOFMEMORY;
01043         GetTimeFormatW(ctx->lcid, 0, &st, NULL, date_str, len);
01044 
01045         V_VT(retv) = VT_BSTR;
01046         V_BSTR(retv) = date_str;
01047     }
01048     return S_OK;
01049 }
01050 
01051 /* ECMA-262 3rd Edition    15.9.5.9 */
01052 static HRESULT Date_getTime(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01053         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01054 {
01055     DateInstance *date;
01056 
01057     TRACE("\n");
01058 
01059     if(!(date = date_this(jsthis)))
01060         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01061 
01062     if(retv)
01063         num_set_val(retv, date->time);
01064     return S_OK;
01065 }
01066 
01067 /* ECMA-262 3rd Edition    15.9.5.10 */
01068 static HRESULT Date_getFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01069         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01070 {
01071     DateInstance *date;
01072 
01073     TRACE("\n");
01074 
01075     if(!(date = date_this(jsthis)))
01076         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01077 
01078     if(retv) {
01079         DOUBLE time = local_time(date->time, date);
01080 
01081         num_set_val(retv, year_from_time(time));
01082     }
01083     return S_OK;
01084 }
01085 
01086 /* ECMA-262 3rd Edition    15.9.5.11 */
01087 static HRESULT Date_getUTCFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01088         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01089 {
01090     DateInstance *date;
01091 
01092     TRACE("\n");
01093 
01094     if(!(date = date_this(jsthis)))
01095         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01096 
01097     if(retv)
01098         num_set_val(retv, year_from_time(date->time));
01099     return S_OK;
01100 }
01101 
01102 /* ECMA-262 3rd Edition    15.9.5.12 */
01103 static HRESULT Date_getMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01104         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01105 {
01106     DateInstance *date;
01107 
01108     TRACE("\n");
01109 
01110     if(!(date = date_this(jsthis)))
01111         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01112 
01113     if(retv) {
01114         DOUBLE time = local_time(date->time, date);
01115 
01116         num_set_val(retv, month_from_time(time));
01117     }
01118     return S_OK;
01119 }
01120 
01121 /* ECMA-262 3rd Edition    15.9.5.13 */
01122 static HRESULT Date_getUTCMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01123         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01124 {
01125     DateInstance *date;
01126 
01127     TRACE("\n");
01128 
01129     if(!(date = date_this(jsthis)))
01130         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01131 
01132     if(retv)
01133         num_set_val(retv, month_from_time(date->time));
01134     return S_OK;
01135 }
01136 
01137 /* ECMA-262 3rd Edition    15.9.5.14 */
01138 static HRESULT Date_getDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01139         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01140 {
01141     DateInstance *date;
01142 
01143     TRACE("\n");
01144 
01145     if(!(date = date_this(jsthis)))
01146         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01147 
01148     if(retv) {
01149         DOUBLE time = local_time(date->time, date);
01150 
01151         num_set_val(retv, date_from_time(time));
01152     }
01153     return S_OK;
01154 }
01155 
01156 /* ECMA-262 3rd Edition    15.9.5.15 */
01157 static HRESULT Date_getUTCDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01158         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01159 {
01160     DateInstance *date;
01161 
01162     TRACE("\n");
01163 
01164     if(!(date = date_this(jsthis)))
01165         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01166 
01167     if(retv)
01168         num_set_val(retv, date_from_time(date->time));
01169     return S_OK;
01170 }
01171 
01172 /* ECMA-262 3rd Edition    15.9.5.16 */
01173 static HRESULT Date_getDay(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01174         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01175 {
01176     DateInstance *date;
01177 
01178     TRACE("\n");
01179 
01180     if(!(date = date_this(jsthis)))
01181         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01182 
01183     if(retv) {
01184         DOUBLE time = local_time(date->time, date);
01185 
01186         num_set_val(retv, week_day(time));
01187     }
01188     return S_OK;
01189 }
01190 
01191 /* ECMA-262 3rd Edition    15.9.5.17 */
01192 static HRESULT Date_getUTCDay(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01193         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01194 {
01195     DateInstance *date;
01196 
01197     TRACE("\n");
01198 
01199     if(!(date = date_this(jsthis)))
01200         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01201 
01202     if(retv)
01203         num_set_val(retv, week_day(date->time));
01204     return S_OK;
01205 }
01206 
01207 /* ECMA-262 3rd Edition    15.9.5.18 */
01208 static HRESULT Date_getHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01209         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01210 {
01211     DateInstance *date;
01212 
01213     TRACE("\n");
01214 
01215     if(!(date = date_this(jsthis)))
01216         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01217 
01218     if(retv) {
01219         DOUBLE time = local_time(date->time, date);
01220 
01221         num_set_val(retv, hour_from_time(time));
01222     }
01223     return S_OK;
01224 }
01225 
01226 /* ECMA-262 3rd Edition    15.9.5.19 */
01227 static HRESULT Date_getUTCHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01228         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01229 {
01230     DateInstance *date;
01231 
01232     TRACE("\n");
01233 
01234     if(!(date = date_this(jsthis)))
01235         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01236 
01237     if(retv)
01238         num_set_val(retv, hour_from_time(date->time));
01239     return S_OK;
01240 }
01241 
01242 /* ECMA-262 3rd Edition    15.9.5.20 */
01243 static HRESULT Date_getMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01244         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01245 {
01246     DateInstance *date;
01247 
01248     TRACE("\n");
01249 
01250     if(!(date = date_this(jsthis)))
01251         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01252 
01253     if(retv) {
01254         DOUBLE time = local_time(date->time, date);
01255 
01256         num_set_val(retv, min_from_time(time));
01257     }
01258     return S_OK;
01259 }
01260 
01261 /* ECMA-262 3rd Edition    15.9.5.21 */
01262 static HRESULT Date_getUTCMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01263         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01264 {
01265     DateInstance *date;
01266 
01267     TRACE("\n");
01268 
01269     if(!(date = date_this(jsthis)))
01270         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01271 
01272     if(retv)
01273         num_set_val(retv, min_from_time(date->time));
01274     return S_OK;
01275 }
01276 
01277 /* ECMA-262 3rd Edition    15.9.5.22 */
01278 static HRESULT Date_getSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01279         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01280 {
01281     DateInstance *date;
01282 
01283     TRACE("\n");
01284 
01285     if(!(date = date_this(jsthis)))
01286         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01287 
01288     if(retv) {
01289         DOUBLE time = local_time(date->time, date);
01290 
01291         num_set_val(retv, sec_from_time(time));
01292     }
01293     return S_OK;
01294 }
01295 
01296 /* ECMA-262 3rd Edition    15.9.5.23 */
01297 static HRESULT Date_getUTCSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01298         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01299 {
01300     DateInstance *date;
01301 
01302     TRACE("\n");
01303 
01304     if(!(date = date_this(jsthis)))
01305         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01306 
01307     if(retv)
01308         num_set_val(retv, sec_from_time(date->time));
01309     return S_OK;
01310 }
01311 
01312 /* ECMA-262 3rd Edition    15.9.5.24 */
01313 static HRESULT Date_getMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01314         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01315 {
01316     DateInstance *date;
01317 
01318     TRACE("\n");
01319 
01320     if(!(date = date_this(jsthis)))
01321         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01322 
01323     if(retv) {
01324         DOUBLE time = local_time(date->time, date);
01325 
01326         num_set_val(retv, ms_from_time(time));
01327     }
01328     return S_OK;
01329 }
01330 
01331 /* ECMA-262 3rd Edition    15.9.5.25 */
01332 static HRESULT Date_getUTCMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01333         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01334 {
01335     DateInstance *date;
01336 
01337     TRACE("\n");
01338 
01339     if(!(date = date_this(jsthis)))
01340         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01341 
01342     if(retv)
01343         num_set_val(retv, ms_from_time(date->time));
01344     return S_OK;
01345 }
01346 
01347 /* ECMA-262 3rd Edition    15.9.5.26 */
01348 static HRESULT Date_getTimezoneOffset(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01349         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01350 {
01351     DateInstance *date;
01352 
01353     TRACE("\n");
01354 
01355     if(!(date = date_this(jsthis)))
01356         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01357 
01358     if(retv)
01359         num_set_val(retv, floor(
01360                     (date->time-local_time(date->time, date))/MS_PER_MINUTE));
01361     return S_OK;
01362 }
01363 
01364 /* ECMA-262 3rd Edition    15.9.5.27 */
01365 static HRESULT Date_setTime(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01366         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01367 {
01368     VARIANT v;
01369     HRESULT hres;
01370     DateInstance *date;
01371 
01372     TRACE("\n");
01373 
01374     if(!(date = date_this(jsthis)))
01375         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01376 
01377     if(!arg_cnt(dp))
01378         return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
01379 
01380     hres = to_number(ctx, get_arg(dp, 0), ei, &v);
01381     if(FAILED(hres))
01382         return hres;
01383 
01384     date->time = time_clip(num_val(&v));
01385 
01386     if(retv)
01387         num_set_val(retv, date->time);
01388 
01389     return S_OK;
01390 }
01391 
01392 /* ECMA-262 3rd Edition    15.9.5.28 */
01393 static HRESULT Date_setMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01394         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01395 {
01396     VARIANT v;
01397     HRESULT hres;
01398     DateInstance *date;
01399     DOUBLE t;
01400 
01401     TRACE("\n");
01402 
01403     if(!(date = date_this(jsthis)))
01404         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01405 
01406     if(!arg_cnt(dp))
01407         return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
01408 
01409     hres = to_number(ctx, get_arg(dp, 0), ei, &v);
01410     if(FAILED(hres))
01411         return hres;
01412 
01413     t = local_time(date->time, date);
01414     t = make_date(day(t), make_time(hour_from_time(t), min_from_time(t),
01415                 sec_from_time(t), num_val(&v)));
01416     date->time = time_clip(utc(t, date));
01417 
01418     if(retv)
01419         num_set_val(retv, date->time);
01420 
01421     return S_OK;
01422 }
01423 
01424 /* ECMA-262 3rd Edition    15.9.5.29 */
01425 static HRESULT Date_setUTCMilliseconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01426         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01427 {
01428     VARIANT v;
01429     HRESULT hres;
01430     DateInstance *date;
01431     DOUBLE t;
01432 
01433     TRACE("\n");
01434 
01435     if(!(date = date_this(jsthis)))
01436         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01437 
01438     if(!arg_cnt(dp))
01439         return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
01440 
01441     hres = to_number(ctx, get_arg(dp, 0), ei, &v);
01442     if(FAILED(hres))
01443         return hres;
01444 
01445     t = date->time;
01446     t = make_date(day(t), make_time(hour_from_time(t), min_from_time(t),
01447                 sec_from_time(t), num_val(&v)));
01448     date->time = time_clip(t);
01449 
01450     if(retv)
01451         num_set_val(retv, date->time);
01452 
01453     return S_OK;
01454 }
01455 
01456 /* ECMA-262 3rd Edition    15.9.5.30 */
01457 static HRESULT Date_setSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01458         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01459 {
01460     VARIANT v;
01461     HRESULT hres;
01462     DateInstance *date;
01463     DOUBLE t, sec, ms;
01464 
01465     TRACE("\n");
01466 
01467     if(!(date = date_this(jsthis)))
01468         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01469 
01470     if(!arg_cnt(dp))
01471         return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
01472 
01473     t = local_time(date->time, date);
01474 
01475     hres = to_number(ctx, get_arg(dp, 0), ei, &v);
01476     if(FAILED(hres))
01477         return hres;
01478     sec = num_val(&v);
01479 
01480     if(arg_cnt(dp) > 1) {
01481         hres = to_number(ctx, get_arg(dp, 1), ei, &v);
01482         if(FAILED(hres))
01483             return hres;
01484         ms = num_val(&v);
01485     }
01486     else ms = ms_from_time(t);
01487 
01488     t = make_date(day(t), make_time(hour_from_time(t),
01489                 min_from_time(t), sec, ms));
01490     date->time = time_clip(utc(t, date));
01491 
01492     if(retv)
01493         num_set_val(retv, date->time);
01494 
01495     return S_OK;
01496 }
01497 
01498 /* ECMA-262 3rd Edition    15.9.5.31 */
01499 static HRESULT Date_setUTCSeconds(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01500         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01501 {
01502     VARIANT v;
01503     HRESULT hres;
01504     DateInstance *date;
01505     DOUBLE t, sec, ms;
01506 
01507     TRACE("\n");
01508 
01509     if(!(date = date_this(jsthis)))
01510         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01511 
01512     if(!arg_cnt(dp))
01513         return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
01514 
01515     t = date->time;
01516 
01517     hres = to_number(ctx, get_arg(dp, 0), ei, &v);
01518     if(FAILED(hres))
01519         return hres;
01520     sec = num_val(&v);
01521 
01522     if(arg_cnt(dp) > 1) {
01523         hres = to_number(ctx, get_arg(dp, 1), ei, &v);
01524         if(FAILED(hres))
01525             return hres;
01526         ms = num_val(&v);
01527     }
01528     else ms = ms_from_time(t);
01529 
01530     t = make_date(day(t), make_time(hour_from_time(t),
01531                 min_from_time(t), sec, ms));
01532     date->time = time_clip(t);
01533 
01534     if(retv)
01535         num_set_val(retv, date->time);
01536 
01537     return S_OK;
01538 }
01539 
01540 /* ECMA-262 3rd Edition    15.9.5.33 */
01541 static HRESULT Date_setMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01542         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01543 {
01544     VARIANT v;
01545     HRESULT hres;
01546     DateInstance *date;
01547     DOUBLE t, min, sec, ms;
01548 
01549     TRACE("\n");
01550 
01551     if(!(date = date_this(jsthis)))
01552         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01553 
01554     if(!arg_cnt(dp))
01555         return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
01556 
01557     t = local_time(date->time, date);
01558 
01559     hres = to_number(ctx, get_arg(dp, 0), ei, &v);
01560     if(FAILED(hres))
01561         return hres;
01562     min = num_val(&v);
01563 
01564     if(arg_cnt(dp) > 1) {
01565         hres = to_number(ctx, get_arg(dp, 1), ei, &v);
01566         if(FAILED(hres))
01567             return hres;
01568         sec = num_val(&v);
01569     }
01570     else sec = sec_from_time(t);
01571 
01572     if(arg_cnt(dp) > 2) {
01573         hres = to_number(ctx, get_arg(dp, 2), ei, &v);
01574         if(FAILED(hres))
01575             return hres;
01576         ms = num_val(&v);
01577     }
01578     else ms = ms_from_time(t);
01579 
01580     t = make_date(day(t), make_time(hour_from_time(t),
01581                 min, sec, ms));
01582     date->time = time_clip(utc(t, date));
01583 
01584     if(retv)
01585         num_set_val(retv, date->time);
01586 
01587     return S_OK;
01588 }
01589 
01590 /* ECMA-262 3rd Edition    15.9.5.34 */
01591 static HRESULT Date_setUTCMinutes(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01592         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01593 {
01594     VARIANT v;
01595     HRESULT hres;
01596     DateInstance *date;
01597     DOUBLE t, min, sec, ms;
01598 
01599     TRACE("\n");
01600 
01601     if(!(date = date_this(jsthis)))
01602         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01603 
01604     if(!arg_cnt(dp))
01605         return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
01606 
01607     t = date->time;
01608 
01609     hres = to_number(ctx, get_arg(dp, 0), ei, &v);
01610     if(FAILED(hres))
01611         return hres;
01612     min = num_val(&v);
01613 
01614     if(arg_cnt(dp) > 1) {
01615         hres = to_number(ctx, get_arg(dp, 1), ei, &v);
01616         if(FAILED(hres))
01617             return hres;
01618         sec = num_val(&v);
01619     }
01620     else sec = sec_from_time(t);
01621 
01622     if(arg_cnt(dp) > 2) {
01623         hres = to_number(ctx, get_arg(dp, 2), ei, &v);
01624         if(FAILED(hres))
01625             return hres;
01626         ms = num_val(&v);
01627     }
01628     else ms = ms_from_time(t);
01629 
01630     t = make_date(day(t), make_time(hour_from_time(t),
01631                 min, sec, ms));
01632     date->time = time_clip(t);
01633 
01634     if(retv)
01635         num_set_val(retv, date->time);
01636 
01637     return S_OK;
01638 }
01639 
01640 /* ECMA-262 3rd Edition    15.9.5.35 */
01641 static HRESULT Date_setHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01642         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01643 {
01644     VARIANT v;
01645     HRESULT hres;
01646     DateInstance *date;
01647     DOUBLE t, hour, min, sec, ms;
01648 
01649     TRACE("\n");
01650 
01651     if(!(date = date_this(jsthis)))
01652         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01653 
01654     if(!arg_cnt(dp))
01655         return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
01656 
01657     t = local_time(date->time, date);
01658 
01659     hres = to_number(ctx, get_arg(dp, 0), ei, &v);
01660     if(FAILED(hres))
01661         return hres;
01662     hour = num_val(&v);
01663 
01664     if(arg_cnt(dp) > 1) {
01665         hres = to_number(ctx, get_arg(dp, 1), ei, &v);
01666         if(FAILED(hres))
01667             return hres;
01668         min = num_val(&v);
01669     }
01670     else min = min_from_time(t);
01671 
01672     if(arg_cnt(dp) > 2) {
01673         hres = to_number(ctx, get_arg(dp, 2), ei, &v);
01674         if(FAILED(hres))
01675             return hres;
01676         sec = num_val(&v);
01677     }
01678     else sec = sec_from_time(t);
01679 
01680     if(arg_cnt(dp) > 3) {
01681         hres = to_number(ctx, get_arg(dp, 3), ei, &v);
01682         if(FAILED(hres))
01683             return hres;
01684         ms = num_val(&v);
01685     }
01686     else ms = ms_from_time(t);
01687 
01688     t = make_date(day(t), make_time(hour, min, sec, ms));
01689     date->time = time_clip(utc(t, date));
01690 
01691     if(retv)
01692         num_set_val(retv, date->time);
01693 
01694     return S_OK;
01695 }
01696 
01697 /* ECMA-262 3rd Edition    15.9.5.36 */
01698 static HRESULT Date_setUTCHours(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01699         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01700 {
01701     DateInstance *date;
01702     VARIANT v;
01703     HRESULT hres;
01704     DOUBLE t, hour, min, sec, ms;
01705 
01706     TRACE("\n");
01707 
01708     if(!(date = date_this(jsthis)))
01709         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01710 
01711     if(!arg_cnt(dp))
01712         return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
01713 
01714     t = date->time;
01715 
01716     hres = to_number(ctx, get_arg(dp, 0), ei, &v);
01717     if(FAILED(hres))
01718         return hres;
01719     hour = num_val(&v);
01720 
01721     if(arg_cnt(dp) > 1) {
01722         hres = to_number(ctx, get_arg(dp, 1), ei, &v);
01723         if(FAILED(hres))
01724             return hres;
01725         min = num_val(&v);
01726     }
01727     else min = min_from_time(t);
01728 
01729     if(arg_cnt(dp) > 2) {
01730         hres = to_number(ctx, get_arg(dp, 2), ei, &v);
01731         if(FAILED(hres))
01732             return hres;
01733         sec = num_val(&v);
01734     }
01735     else sec = sec_from_time(t);
01736 
01737     if(arg_cnt(dp) > 3) {
01738         hres = to_number(ctx, get_arg(dp, 3), ei, &v);
01739         if(FAILED(hres))
01740             return hres;
01741         ms = num_val(&v);
01742     }
01743     else ms = ms_from_time(t);
01744 
01745     t = make_date(day(t), make_time(hour, min, sec, ms));
01746     date->time = time_clip(t);
01747 
01748     if(retv)
01749         num_set_val(retv, date->time);
01750 
01751     return S_OK;
01752 }
01753 
01754 /* ECMA-262 3rd Edition    15.9.5.36 */
01755 static HRESULT Date_setDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01756         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01757 {
01758     VARIANT v;
01759     HRESULT hres;
01760     DateInstance *date;
01761     DOUBLE t;
01762 
01763     TRACE("\n");
01764 
01765     if(!(date = date_this(jsthis)))
01766         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01767 
01768     if(!arg_cnt(dp))
01769         return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
01770 
01771     hres = to_number(ctx, get_arg(dp, 0), ei, &v);
01772     if(FAILED(hres))
01773         return hres;
01774 
01775     t = local_time(date->time, date);
01776     t = make_date(make_day(year_from_time(t), month_from_time(t),
01777                 num_val(&v)), time_within_day(t));
01778     date->time = time_clip(utc(t, date));
01779 
01780     if(retv)
01781         num_set_val(retv, date->time);
01782 
01783     return S_OK;
01784 }
01785 
01786 /* ECMA-262 3rd Edition    15.9.5.37 */
01787 static HRESULT Date_setUTCDate(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01788         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01789 {
01790     VARIANT v;
01791     HRESULT hres;
01792     DateInstance *date;
01793     DOUBLE t;
01794 
01795     TRACE("\n");
01796 
01797     if(!(date = date_this(jsthis)))
01798         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01799 
01800     if(!arg_cnt(dp))
01801         return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
01802 
01803     hres = to_number(ctx, get_arg(dp, 0), ei, &v);
01804     if(FAILED(hres))
01805         return hres;
01806 
01807     t = date->time;
01808     t = make_date(make_day(year_from_time(t), month_from_time(t),
01809                 num_val(&v)), time_within_day(t));
01810     date->time = time_clip(t);
01811 
01812     if(retv)
01813         num_set_val(retv, date->time);
01814 
01815     return S_OK;
01816 }
01817 
01818 /* ECMA-262 3rd Edition    15.9.5.38 */
01819 static HRESULT Date_setMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01820         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01821 {
01822     VARIANT v;
01823     HRESULT hres;
01824     DateInstance *date;
01825     DOUBLE t, month, ddate;
01826 
01827     TRACE("\n");
01828 
01829     if(!(date = date_this(jsthis)))
01830         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01831 
01832     if(!arg_cnt(dp))
01833         return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
01834 
01835     t = local_time(date->time, date);
01836 
01837     hres = to_number(ctx, get_arg(dp, 0), ei, &v);
01838     if(FAILED(hres))
01839         return hres;
01840     month = num_val(&v);
01841 
01842     if(arg_cnt(dp) > 1) {
01843         hres = to_number(ctx, get_arg(dp, 1), ei, &v);
01844         if(FAILED(hres))
01845             return hres;
01846         ddate = num_val(&v);
01847     }
01848     else ddate = date_from_time(t);
01849 
01850     t = make_date(make_day(year_from_time(t), month, ddate),
01851             time_within_day(t));
01852     date->time = time_clip(utc(t, date));
01853 
01854     if(retv)
01855         num_set_val(retv, date->time);
01856 
01857     return S_OK;
01858 }
01859 
01860 /* ECMA-262 3rd Edition    15.9.5.39 */
01861 static HRESULT Date_setUTCMonth(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01862         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01863 {
01864     VARIANT v;
01865     HRESULT hres;
01866     DateInstance *date;
01867     DOUBLE t, month, ddate;
01868 
01869     TRACE("\n");
01870 
01871     if(!(date = date_this(jsthis)))
01872         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01873 
01874     if(!arg_cnt(dp))
01875         return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
01876 
01877     t = date->time;
01878 
01879     hres = to_number(ctx, get_arg(dp, 0), ei, &v);
01880     if(FAILED(hres))
01881         return hres;
01882     month = num_val(&v);
01883 
01884     if(arg_cnt(dp) > 1) {
01885         hres = to_number(ctx, get_arg(dp, 1), ei, &v);
01886         if(FAILED(hres))
01887             return hres;
01888         ddate = num_val(&v);
01889     }
01890     else ddate = date_from_time(t);
01891 
01892     t = make_date(make_day(year_from_time(t), month, ddate),
01893             time_within_day(t));
01894     date->time = time_clip(t);
01895 
01896     if(retv)
01897         num_set_val(retv, date->time);
01898 
01899     return S_OK;
01900 }
01901 
01902 /* ECMA-262 3rd Edition    15.9.5.40 */
01903 static HRESULT Date_setFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01904         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01905 {
01906     VARIANT v;
01907     HRESULT hres;
01908     DateInstance *date;
01909     DOUBLE t, year, month, ddate;
01910 
01911     TRACE("\n");
01912 
01913     if(!(date = date_this(jsthis)))
01914         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01915 
01916     if(!arg_cnt(dp))
01917         return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
01918 
01919     t = local_time(date->time, date);
01920 
01921     hres = to_number(ctx, get_arg(dp, 0), ei, &v);
01922     if(FAILED(hres))
01923         return hres;
01924     year = num_val(&v);
01925 
01926     if(arg_cnt(dp) > 1) {
01927         hres = to_number(ctx, get_arg(dp, 1), ei, &v);
01928         if(FAILED(hres))
01929             return hres;
01930         month = num_val(&v);
01931     }
01932     else month = month_from_time(t);
01933 
01934     if(arg_cnt(dp) > 2) {
01935         hres = to_number(ctx, get_arg(dp, 2), ei, &v);
01936         if(FAILED(hres))
01937             return hres;
01938         ddate = num_val(&v);
01939     }
01940     else ddate = date_from_time(t);
01941 
01942     t = make_date(make_day(year, month, ddate), time_within_day(t));
01943     date->time = time_clip(utc(t, date));
01944 
01945     if(retv)
01946         num_set_val(retv, date->time);
01947 
01948     return S_OK;
01949 }
01950 
01951 /* ECMA-262 3rd Edition    15.9.5.41 */
01952 static HRESULT Date_setUTCFullYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
01953         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
01954 {
01955     VARIANT v;
01956     HRESULT hres;
01957     DateInstance *date;
01958     DOUBLE t, year, month, ddate;
01959 
01960     TRACE("\n");
01961 
01962     if(!(date = date_this(jsthis)))
01963         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
01964 
01965     if(!arg_cnt(dp))
01966         return throw_type_error(ctx, ei, IDS_ARG_NOT_OPT, NULL);
01967 
01968     t = date->time;
01969 
01970     hres = to_number(ctx, get_arg(dp, 0), ei, &v);
01971     if(FAILED(hres))
01972         return hres;
01973     year = num_val(&v);
01974 
01975     if(arg_cnt(dp) > 1) {
01976         hres = to_number(ctx, get_arg(dp, 1), ei, &v);
01977         if(FAILED(hres))
01978             return hres;
01979         month = num_val(&v);
01980     }
01981     else month = month_from_time(t);
01982 
01983     if(arg_cnt(dp) > 2) {
01984         hres = to_number(ctx, get_arg(dp, 2), ei, &v);
01985         if(FAILED(hres))
01986             return hres;
01987         ddate = num_val(&v);
01988     }
01989     else ddate = date_from_time(t);
01990 
01991     t = make_date(make_day(year, month, ddate), time_within_day(t));
01992     date->time = time_clip(t);
01993 
01994     if(retv)
01995         num_set_val(retv, date->time);
01996 
01997     return S_OK;
01998 }
01999 
02000 /* ECMA-262 3rd Edition    B2.4 */
02001 static HRESULT Date_getYear(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
02002         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
02003 {
02004     DateInstance *date;
02005     DOUBLE t, year;
02006 
02007     TRACE("\n");
02008 
02009     if(!(date = date_this(jsthis)))
02010         return throw_type_error(ctx, ei, IDS_NOT_DATE, NULL);
02011 
02012     t = local_time(date->time, date);
02013     if(isnan(t)) {
02014         if(retv)
02015             num_set_nan(retv);
02016         return S_OK;
02017     }
02018 
02019     year = year_from_time(t);
02020     if(retv)
02021         num_set_val(retv, (1900<=year && year<2000)?year-1900:year);
02022 
02023     return S_OK;
02024 }
02025 
02026 static HRESULT Date_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
02027         VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
02028 {
02029     TRACE("\n");
02030 
02031     switch(flags) {
02032     case INVOKE_FUNC:
02033         return throw_type_error(ctx, ei, IDS_NOT_FUNC, NULL);
02034     default:
02035         FIXME("unimplemented flags %x\n", flags);
02036         return E_NOTIMPL;
02037     }
02038 
02039     return S_OK;
02040 }
02041 
02042 static const builtin_prop_t Date_props[] = {
02043     {getDateW,               Date_getDate,               PROPF_METHOD},
02044     {getDayW,                Date_getDay,                PROPF_METHOD},
02045     {getFullYearW,           Date_getFullYear,           PROPF_METHOD},
02046     {getHoursW,              Date_getHours,              PROPF_METHOD},
02047     {getMillisecondsW,       Date_getMilliseconds,       PROPF_METHOD},
02048     {getMinutesW,            Date_getMinutes,            PROPF_METHOD},
02049     {getMonthW,              Date_getMonth,              PROPF_METHOD},
02050     {getSecondsW,            Date_getSeconds,            PROPF_METHOD},
02051     {getTimeW,               Date_getTime,               PROPF_METHOD},
02052     {getTimezoneOffsetW,     Date_getTimezoneOffset,     PROPF_METHOD},
02053     {getUTCDateW,            Date_getUTCDate,            PROPF_METHOD},
02054     {getUTCDayW,             Date_getUTCDay,             PROPF_METHOD},
02055     {getUTCFullYearW,        Date_getUTCFullYear,        PROPF_METHOD},
02056     {getUTCHoursW,           Date_getUTCHours,           PROPF_METHOD},
02057     {getUTCMillisecondsW,    Date_getUTCMilliseconds,    PROPF_METHOD},
02058     {getUTCMinutesW,         Date_getUTCMinutes,         PROPF_METHOD},
02059     {getUTCMonthW,           Date_getUTCMonth,           PROPF_METHOD},
02060     {getUTCSecondsW,         Date_getUTCSeconds,         PROPF_METHOD},
02061     {getYearW,               Date_getYear,               PROPF_METHOD},
02062     {setDateW,               Date_setDate,               PROPF_METHOD|1},
02063     {setFullYearW,           Date_setFullYear,           PROPF_METHOD|3},
02064     {setHoursW,              Date_setHours,              PROPF_METHOD|4},
02065     {setMillisecondsW,       Date_setMilliseconds,       PROPF_METHOD|1},
02066     {setMinutesW,            Date_setMinutes,            PROPF_METHOD|3},
02067     {setMonthW,              Date_setMonth,              PROPF_METHOD|2},
02068     {setSecondsW,            Date_setSeconds,            PROPF_METHOD|2},
02069     {setTimeW,               Date_setTime,               PROPF_METHOD|1},
02070     {setUTCDateW,            Date_setUTCDate,            PROPF_METHOD|1},
02071     {setUTCFullYearW,        Date_setUTCFullYear,        PROPF_METHOD|3},
02072     {setUTCHoursW,           Date_setUTCHours,           PROPF_METHOD|4},
02073     {setUTCMillisecondsW,    Date_setUTCMilliseconds,    PROPF_METHOD|1},
02074     {setUTCMinutesW,         Date_setUTCMinutes,         PROPF_METHOD|3},
02075     {setUTCMonthW,           Date_setUTCMonth,           PROPF_METHOD|2},
02076     {setUTCSecondsW,         Date_setUTCSeconds,         PROPF_METHOD|2},
02077     {toDateStringW,          Date_toDateString,          PROPF_METHOD},
02078     {toGMTStringW,           Date_toGMTString,           PROPF_METHOD},
02079     {toLocaleDateStringW,    Date_toLocaleDateString,    PROPF_METHOD},
02080     {toLocaleStringW,        Date_toLocaleString,        PROPF_METHOD},
02081     {toLocaleTimeStringW,    Date_toLocaleTimeString,    PROPF_METHOD},
02082     {toStringW,              Date_toString,              PROPF_METHOD},
02083     {toTimeStringW,          Date_toTimeString,          PROPF_METHOD},
02084     {toUTCStringW,           Date_toUTCString,           PROPF_METHOD},
02085     {valueOfW,               Date_valueOf,               PROPF_METHOD},
02086 };
02087 
02088 static const builtin_info_t Date_info = {
02089     JSCLASS_DATE,
02090     {NULL, Date_value, 0},
02091     sizeof(Date_props)/sizeof(*Date_props),
02092     Date_props,
02093     NULL,
02094     NULL
02095 };
02096 
02097 static HRESULT create_date(script_ctx_t *ctx, DispatchEx *object_prototype, DOUBLE time, DispatchEx **ret)
02098 {
02099     DateInstance *date;
02100     HRESULT hres;
02101     TIME_ZONE_INFORMATION tzi;
02102 
02103     GetTimeZoneInformation(&tzi);
02104 
02105     date = heap_alloc_zero(sizeof(DateInstance));
02106     if(!date)
02107         return E_OUTOFMEMORY;
02108 
02109     if(object_prototype)
02110         hres = init_dispex(&date->dispex, ctx, &Date_info, object_prototype);
02111     else
02112         hres = init_dispex_from_constr(&date->dispex, ctx, &Date_info, ctx->date_constr);
02113     if(FAILED(hres)) {
02114         heap_free(date);
02115         return hres;
02116     }
02117 
02118     date->time = time;
02119     date->bias = tzi.Bias;
02120     date->standardDate = tzi.StandardDate;
02121     date->standardBias = tzi.StandardBias;
02122     date->daylightDate = tzi.DaylightDate;
02123     date->daylightBias = tzi.DaylightBias;
02124 
02125     *ret = &date->dispex;
02126     return S_OK;
02127 }
02128 
02129 static inline HRESULT date_parse(BSTR input, VARIANT *retv) {
02130     static const DWORD string_ids[] = { LOCALE_SMONTHNAME12, LOCALE_SMONTHNAME11,
02131         LOCALE_SMONTHNAME10, LOCALE_SMONTHNAME9, LOCALE_SMONTHNAME8,
02132         LOCALE_SMONTHNAME7, LOCALE_SMONTHNAME6, LOCALE_SMONTHNAME5,
02133         LOCALE_SMONTHNAME4, LOCALE_SMONTHNAME3, LOCALE_SMONTHNAME2,
02134         LOCALE_SMONTHNAME1, LOCALE_SDAYNAME7, LOCALE_SDAYNAME1,
02135         LOCALE_SDAYNAME2, LOCALE_SDAYNAME3, LOCALE_SDAYNAME4,
02136         LOCALE_SDAYNAME5, LOCALE_SDAYNAME6 };
02137     BSTR strings[sizeof(string_ids)/sizeof(DWORD)];
02138 
02139     BSTR parse;
02140     int input_len, parse_len = 0, nest_level = 0, i, size;
02141     int year = 0, month = 0, day = 0, hour = 0, min = 0, sec = 0;
02142     int ms = 0, offset = 0, hour_adjust = 0;
02143     BOOL set_year = FALSE, set_month = FALSE, set_day = FALSE, set_hour = FALSE;
02144     BOOL set_offset = FALSE, set_era = FALSE, ad = TRUE, set_am = FALSE, am = TRUE;
02145     BOOL set_hour_adjust = TRUE;
02146     TIME_ZONE_INFORMATION tzi;
02147     DateInstance di;
02148     DWORD lcid_en;
02149 
02150     if(retv) num_set_nan(retv);
02151 
02152     input_len = SysStringLen(input);
02153     for(i=0; i<input_len; i++) {
02154         if(input[i] == '(') nest_level++;
02155         else if(input[i] == ')') {
02156             nest_level--;
02157             if(nest_level<0)
02158                 return S_OK;
02159         }
02160         else if(!nest_level) parse_len++;
02161     }
02162 
02163     parse = SysAllocStringLen(NULL, parse_len);
02164     if(!parse)
02165         return E_OUTOFMEMORY;
02166     nest_level = 0;
02167     parse_len = 0;
02168     for(i=0; i<input_len; i++) {
02169         if(input[i] == '(') nest_level++;
02170         else if(input[i] == ')') nest_level--;
02171         else if(!nest_level) parse[parse_len++] = toupperW(input[i]);
02172     }
02173 
02174     GetTimeZoneInformation(&tzi);
02175     di.bias = tzi.Bias;
02176     di.standardDate = tzi.StandardDate;
02177     di.standardBias = tzi.StandardBias;
02178     di.daylightDate = tzi.DaylightDate;
02179     di.daylightBias = tzi.DaylightBias;
02180 
02181     lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT);
02182     for(i=0; i<sizeof(string_ids)/sizeof(DWORD); i++) {
02183         size = GetLocaleInfoW(lcid_en, string_ids[i], NULL, 0);
02184         strings[i] = SysAllocStringLen(NULL, size);
02185         if(!strings[i]) {
02186             i--;
02187             while(i-- >= 0)
02188                 SysFreeString(strings[i]);
02189             SysFreeString(parse);
02190             return E_OUTOFMEMORY;
02191         }
02192         GetLocaleInfoW(lcid_en, string_ids[i], strings[i], size);
02193     }
02194 
02195     for(i=0; i<parse_len;) {
02196         while(isspaceW(parse[i])) i++;
02197         if(parse[i] == ',') {
02198             while(parse[i] == ',') i++;
02199             continue;
02200         }
02201 
02202         if(parse[i]>='0' && parse[i]<='9') {
02203             int tmp = atoiW(&parse[i]);
02204             while(parse[i]>='0' && parse[i]<='9') i++;
02205             while(isspaceW(parse[i])) i++;
02206 
02207             if(parse[i] == ':') {
02208                 /* Time */
02209                 if(set_hour) break;
02210                 set_hour = TRUE;
02211 
02212                 hour = tmp;
02213 
02214                 while(parse[i] == ':') i++;
02215                 while(isspaceW(parse[i])) i++;
02216                 if(parse[i]>='0' && parse[i]<='9') {
02217                     min = atoiW(&parse[i]);
02218                     while(parse[i]>='0' && parse[i]<='9') i++;
02219                 }
02220 
02221                 while(isspaceW(parse[i])) i++;
02222                 while(parse[i] == ':') i++;
02223                 while(isspaceW(parse[i])) i++;
02224                 if(parse[i]>='0' && parse[i]<='9') {
02225                     sec = atoiW(&parse[i]);
02226                     while(parse[i]>='0' && parse[i]<='9') i++;
02227                 }
02228             }
02229             else if(parse[i]=='-' || parse[i]=='/') {
02230                 /* Short date */
02231                 if(set_day || set_month || set_year) break;
02232                 set_day = TRUE;
02233                 set_month = TRUE;
02234                 set_year = TRUE;
02235 
02236                 month = tmp-1;
02237 
02238                 while(isspaceW(parse[i])) i++;
02239                 while(parse[i]=='-' || parse[i]=='/') i++;
02240                 while(isspaceW(parse[i])) i++;
02241                 if(parse[i]<'0' || parse[i]>'9') break;
02242                 day = atoiW(&parse[i]);
02243                 while(parse[i]>='0' && parse[i]<='9') i++;
02244 
02245                 while(parse[i]=='-' || parse[i]=='/') i++;
02246                 while(isspaceW(parse[i])) i++;
02247                 if(parse[i]<'0' || parse[i]>'9') break;
02248                 year = atoiW(&parse[i]);
02249                 while(parse[i]>='0' && parse[i]<='9') i++;
02250             }
02251             else if(tmp<0) break;
02252             else if(tmp<70) {
02253                 /* Day */
02254                 if(set_day) break;
02255                 set_day = TRUE;
02256                 day = tmp;
02257             }
02258             else {
02259                 /* Year */
02260                 if(set_year) break;
02261                 set_year = TRUE;
02262                 year = tmp;
02263             }
02264         }
02265         else {
02266             if(parse[i]<'A' || parse[i]>'Z') break;
02267             else if(parse[i]=='B' && (parse[i+1]=='C' ||
02268                         (parse[i+1]=='.' && parse[i+2]=='C'))) {
02269                 /* AD/BC */
02270                 if(set_era) break;
02271                 set_era = TRUE;
02272                 ad = FALSE;
02273 
02274                 i++;
02275                 if(parse[i] == '.') i++;
02276                 i++;
02277                 if(parse[i] == '.') i++;
02278             }
02279             else if(parse[i]=='A' && (parse[i+1]=='D' ||
02280                         (parse[i+1]=='.' && parse[i+2]=='D'))) {
02281                 /* AD/BC */
02282                 if(set_era) break;
02283                 set_era = TRUE;
02284 
02285                 i++;
02286                 if(parse[i] == '.') i++;
02287                 i++;
02288                 if(parse[i] == '.') i++;
02289             }
02290             else if(parse[i+1]<'A' || parse[i+1]>'Z') {
02291                 /* Timezone */
02292                 if(set_offset) break;
02293                 set_offset = TRUE;
02294 
02295                 if(parse[i] <= 'I') hour_adjust = parse[i]-'A'+2;
02296                 else if(parse[i] == 'J') break;
02297                 else if(parse[i] <= 'M') hour_adjust = parse[i]-'K'+11;
02298                 else if(parse[i] <= 'Y') hour_adjust = parse[i]-'N';
02299                 else hour_adjust = 1;
02300 
02301                 i++;
02302                 if(parse[i] == '.') i++;
02303             }
02304             else if(parse[i]=='A' && parse[i+1]=='M') {
02305                 /* AM/PM */
02306                 if(set_am) break;
02307                 set_am = TRUE;
02308                 am = TRUE;
02309                 i += 2;
02310             }
02311             else if(parse[i]=='P' && parse[i+1]=='M') {
02312                 /* AM/PM */
02313                 if(set_am) break;
02314                 set_am = TRUE;
02315                 am = FALSE;
02316                 i += 2;
02317             }
02318             else if((parse[i]=='U' && parse[i+1]=='T' && parse[i+2]=='C')
02319                     || (parse[i]=='G' && parse[i+1]=='M' && parse[i+2]=='T')) {
02320                 /* Timezone */
02321                 BOOL positive = TRUE;
02322 
02323                 if(set_offset) break;
02324                 set_offset = TRUE;
02325                 set_hour_adjust = FALSE;
02326 
02327                 i += 3;
02328                 while(isspaceW(parse[i])) i++;
02329                 if(parse[i] == '-')  positive = FALSE;
02330                 else if(parse[i] != '+') continue;
02331 
02332                 i++;
02333                 while(isspaceW(parse[i])) i++;
02334                 if(parse[i]<'0' || parse[i]>'9') break;
02335                 offset = atoiW(&parse[i]);
02336                 while(parse[i]>='0' && parse[i]<='9') i++;
02337 
02338                 if(offset<24) offset *= 60;
02339                 else offset = (offset/100)*60 + offset%100;
02340 
02341                 if(positive) offset = -offset;
02342             }
02343             else {
02344                 /* Month or garbage */
02345                 int j;
02346 
02347                 for(size=i; parse[size]>='A' && parse[size]<='Z'; size++);
02348                 size -= i;
02349 
02350                 for(j=0; j<sizeof(string_ids)/sizeof(DWORD); j++)
02351                     if(!memicmpW(&parse[i], strings[j], size)) break;
02352 
02353                 if(j < 12) {
02354                     if(set_month) break;
02355                     set_month = TRUE;
02356                     month = 11-j;
02357                 }
02358                 else if(j == sizeof(string_ids)/sizeof(DWORD)) break;
02359 
02360                 i += size;
02361             }
02362         }
02363     }
02364 
02365     if(retv && i==parse_len && set_year && set_month
02366             && set_day && (!set_am || hour<13)) {
02367         if(set_am) {
02368             if(hour == 12) hour = 0;
02369             if(!am) hour += 12;
02370         }
02371 
02372         if(!ad) year = -year+1;
02373         else if(year<100) year += 1900;
02374 
02375         V_VT(retv) = VT_R8;
02376         V_R8(retv) = time_clip(make_date(make_day(year, month, day),
02377                     make_time(hour+hour_adjust, min, sec, ms)) + offset*MS_PER_MINUTE);
02378 
02379         if(set_hour_adjust) V_R8(retv) = utc(V_R8(retv), &di);
02380     }
02381 
02382     for(i=0; i<sizeof(string_ids)/sizeof(DWORD); i++)
02383         SysFreeString(strings[i]);
02384     SysFreeString(parse);
02385 
02386     return S_OK;
02387 }
02388 
02389 static HRESULT DateConstr_parse(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
02390         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
02391 {
02392     BSTR parse_str;
02393     HRESULT hres;
02394 
02395     TRACE("\n");
02396 
02397     if(!arg_cnt(dp)) {
02398         if(retv)
02399             num_set_nan(retv);
02400         return S_OK;
02401     }
02402 
02403     hres = to_string(ctx, get_arg(dp,0), ei, &parse_str);
02404     if(FAILED(hres))
02405         return hres;
02406 
02407     hres = date_parse(parse_str, retv);
02408 
02409     SysFreeString(parse_str);
02410     return hres;
02411 }
02412 
02413 static HRESULT date_utc(script_ctx_t *ctx, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei)
02414 {
02415     VARIANT year, month, vdate, hours, minutes, seconds, ms;
02416     DOUBLE y;
02417     int arg_no = arg_cnt(dp);
02418     HRESULT hres;
02419 
02420     TRACE("\n");
02421 
02422     if(arg_no>0) {
02423         hres = to_number(ctx, get_arg(dp, 0), ei, &year);
02424         if(FAILED(hres))
02425             return hres;
02426         y = num_val(&year);
02427         if(0<=y && y<=99)
02428             y += 1900;
02429     }
02430     else y = 1900;
02431 
02432     if(arg_no>1) {
02433         hres = to_number(ctx, get_arg(dp, 1), ei, &month);
02434         if(FAILED(hres))
02435             return hres;
02436     }
02437     else {
02438         V_VT(&month) = VT_R8;
02439         V_R8(&month) = 0;
02440     }
02441 
02442     if(arg_no>2) {
02443         hres = to_number(ctx, get_arg(dp, 2), ei, &vdate);
02444         if(FAILED(hres))
02445             return hres;
02446     }
02447     else {
02448         V_VT(&vdate) = VT_R8;
02449         V_R8(&vdate) = 1;
02450     }
02451 
02452     if(arg_no>3) {
02453         hres = to_number(ctx, get_arg(dp, 3), ei, &hours);
02454         if(FAILED(hres))
02455             return hres;
02456     }
02457     else {
02458         V_VT(&hours) = VT_R8;
02459         V_R8(&hours) = 0;
02460     }
02461 
02462     if(arg_no>4) {
02463         hres = to_number(ctx, get_arg(dp, 4), ei, &minutes);
02464         if(FAILED(hres))
02465             return hres;
02466     }
02467     else {
02468         V_VT(&minutes) = VT_R8;
02469         V_R8(&minutes) = 0;
02470     }
02471 
02472     if(arg_no>5) {
02473         hres = to_number(ctx, get_arg(dp, 5), ei, &seconds);
02474         if(FAILED(hres))
02475             return hres;
02476     }
02477     else {
02478         V_VT(&seconds) = VT_R8;
02479         V_R8(&seconds) = 0;
02480     }
02481 
02482     if(arg_no>6) {
02483         hres = to_number(ctx, get_arg(dp, 6), ei, &ms);
02484         if(FAILED(hres))
02485             return hres;
02486     }
02487     else {
02488         V_VT(&ms) = VT_R8;
02489         V_R8(&ms) = 0;
02490     }
02491 
02492     if(retv) {
02493         V_VT(retv) = VT_R8;
02494         V_R8(retv) = time_clip(make_date(
02495                     make_day(y, num_val(&month), num_val(&vdate)),
02496                     make_time(num_val(&hours), num_val(&minutes),
02497                     num_val(&seconds), num_val(&ms))));
02498     }
02499 
02500     return S_OK;
02501 }
02502 
02503 static HRESULT DateConstr_UTC(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
02504         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
02505 {
02506     TRACE("\n");
02507 
02508     return date_utc(ctx, dp, retv, ei);
02509 }
02510 
02511 static HRESULT DateConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAMS *dp,
02512         VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
02513 {
02514     DispatchEx *date;
02515     HRESULT hres;
02516 
02517     TRACE("\n");
02518 
02519     switch(flags) {
02520     case DISPATCH_CONSTRUCT:
02521         switch(arg_cnt(dp)) {
02522         /* ECMA-262 3rd Edition    15.9.3.3 */
02523         case 0: {
02524             FILETIME time;
02525             LONGLONG lltime;
02526 
02527             GetSystemTimeAsFileTime(&time);
02528             lltime = ((LONGLONG)time.dwHighDateTime<<32)
02529                 + time.dwLowDateTime;
02530 
02531             hres = create_date(ctx, NULL, lltime/10000-TIME_EPOCH, &date);
02532             if(FAILED(hres))
02533                 return hres;
02534             break;
02535         }
02536 
02537         /* ECMA-262 3rd Edition    15.9.3.2 */
02538         case 1: {
02539             VARIANT prim, num;
02540 
02541             hres = to_primitive(ctx, get_arg(dp,0), ei, &prim, NO_HINT);
02542             if(FAILED(hres))
02543                 return hres;
02544 
02545             if(V_VT(&prim) == VT_BSTR)
02546                 hres = date_parse(V_BSTR(&prim), &num);
02547             else
02548                 hres = to_number(ctx, &prim, ei, &num);
02549 
02550             VariantClear(&prim);
02551             if(FAILED(hres))
02552                 return hres;
02553 
02554             hres = create_date(ctx, NULL, time_clip(num_val(&num)), &date);
02555             if(FAILED(hres))
02556                 return hres;
02557             break;
02558         }
02559 
02560         /* ECMA-262 3rd Edition    15.9.3.1 */
02561         default: {
02562             VARIANT ret_date;
02563             DateInstance *di;
02564 
02565             hres = date_utc(ctx, dp, &ret_date, ei);
02566             if(FAILED(hres))
02567                 return hres;
02568 
02569             hres = create_date(ctx, NULL, num_val(&ret_date), &date);
02570             if(FAILED(hres))
02571                 return hres;
02572 
02573             di = (DateInstance*)date;
02574             di->time = utc(di->time, di);
02575         }
02576         }
02577 
02578         V_VT(retv) = VT_DISPATCH;
02579         V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(date);
02580         return S_OK;
02581 
02582     case INVOKE_FUNC: {
02583         FILETIME system_time, local_time;
02584         LONGLONG lltime;
02585 
02586         GetSystemTimeAsFileTime(&system_time);
02587         FileTimeToLocalFileTime(&system_time, &local_time);
02588         lltime = ((LONGLONG)local_time.dwHighDateTime<<32)
02589             + local_time.dwLowDateTime;
02590 
02591         return date_to_string(lltime/10000-TIME_EPOCH, FALSE, 0, retv);
02592     }
02593 
02594     default:
02595         FIXME("unimplemented flags %x\n", flags);
02596         return E_NOTIMPL;
02597     }
02598 
02599     return S_OK;
02600 }
02601 
02602 static const builtin_prop_t DateConstr_props[] = {
02603     {UTCW,    DateConstr_UTC,    PROPF_METHOD},
02604     {parseW,  DateConstr_parse,  PROPF_METHOD}
02605 };
02606 
02607 static const builtin_info_t DateConstr_info = {
02608     JSCLASS_FUNCTION,
02609     {NULL, Function_value, 0},
02610     sizeof(DateConstr_props)/sizeof(*DateConstr_props),
02611     DateConstr_props,
02612     NULL,
02613     NULL
02614 };
02615 
02616 HRESULT create_date_constr(script_ctx_t *ctx, DispatchEx *object_prototype, DispatchEx **ret)
02617 {
02618     DispatchEx *date;
02619     HRESULT hres;
02620 
02621     static const WCHAR DateW[] = {'D','a','t','e',0};
02622 
02623     hres = create_date(ctx, object_prototype, 0.0, &date);
02624     if(FAILED(hres))
02625         return hres;
02626 
02627     hres = create_builtin_function(ctx, DateConstr_value, DateW, &DateConstr_info,
02628             PROPF_CONSTR|7, date, ret);
02629 
02630     jsdisp_release(date);
02631     return hres;
02632 }

Generated on Thu May 24 2012 04:18:23 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.