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