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