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