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