1/* 2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16package escompat; 17 18// TODO To offer protection against timing attacks and fingerprinting, the precision of `Date.getTime()`, 19// `Date.now()` might get rounded depending on browser (target) settings. 20// In Firefox, the `privacy.reduceTimerPrecision` preference is enabled by default 21// and defaults to 20µs in Firefox 59; in 60 it will be 2ms. 22 23/** Hours in a day. */ 24const hoursPerDay: int = 24; 25 26/** Minutes in an hour. */ 27const minutesPerHour: int = 60; 28 29/** Seconds in a minute. */ 30const secondsPerMinute: long = 60; 31 32/** Milliseconds in a second. */ 33const msPerSecond: long = 1000; 34 35/** msPerMinute == 60000 */ 36const msPerMinute: long = msPerSecond * secondsPerMinute; 37 38/** msPerHour == 3600000 */ 39const msPerHour: long = msPerMinute * minutesPerHour; 40 41/** msPerDay == 86400000 */ 42const msPerDay: long = msPerHour * hoursPerDay; 43 44/** Days in a year */ 45const dayCountInYear: int = 365; 46 47/** Days in a leap year */ 48const dayCountInLeapYear: int = 366; 49 50/** 51 * This gives a range of 8,640,000,000,000,000 milliseconds 52 * to either side of 01 January, 1970 UTC. 53 */ 54const maxDateOffset: long = 8.64e15; 55 56/** Day names */ 57const dayNames: String[] = [ 58 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" 59]; 60 61/** Month names */ 62const monthNames: String[] = [ 63 "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 64]; 65 66/** First day of a month in a year */ 67const firstDayInMonthNormal: int[] = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]; 68/** First day of a month in a leap year */ 69const firstDayInMonthLeap: int[] = [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335]; 70 71/** 72 * Returns first day with respect to year and month 73 * 74 * @param year 75 * 76 * @param month 77 * 78 * @returns first day 79 */ 80function getFirstDayInMonth(year: int, month: int): int { 81 assert (year == 0 || year == 1) && (month >= 0 && month <= 11) : "Invalid year/month pair"; 82 if (year == 0) { 83 return firstDayInMonthNormal[month]; 84 } else { 85 return firstDayInMonthLeap[month]; 86 } 87} 88 89/** 90 * Calculate the elapsed days since Unix Epoch. 91 * 92 * @returns elapsed days since Unix Epoch. 93 */ 94function ecmaDayFromTime(time: long): int { 95 if (time < 0) { 96 time -= msPerDay - 1; 97 } 98 return (time / msPerDay) as int; 99} 100 101/** 102 * @see ECMA-262, 20.4.1.3 103 * 104 * @returns number of days in the given year. 105 */ 106function ecmaDaysInYear(year: int): int { 107 if ((year % 4 != 0) || ((year % 100 == 0) && (year % 400 != 0))) { 108 return dayCountInYear; 109 } 110 111 return dayCountInLeapYear; 112} 113 114/** 115 * @see ECMA-262, 21.4.1.3 116 * 117 * @returns Year, corresponding to the given time. 118 */ 119function ecmaYearFromTime(time: long): int { 120 let approx: int = floor(time / msPerDay / 365.2425) as int + 1970 as int; 121 let yearMs: long = ecmaDayFromYear(approx) * msPerDay; 122 123 if (yearMs > time) { 124 approx--; 125 } 126 127 if ((yearMs + ecmaDaysInYear(approx) * msPerDay) <= time) { 128 approx++; 129 } 130 131 return approx; 132} 133 134/** 135 * @see ECMA-262, 21.4.1.4 136 * 137 * @returns Month number (within year). 138 */ 139function ecmaMonthFromTime(time: long): byte { 140 let year = ecmaYearFromTime(time); 141 let dayWithinYear = ecmaDayFromTime(time) - ecmaDayFromYear(year); 142 143 assert dayWithinYear >= 0 && dayWithinYear < dayCountInLeapYear; 144 145 let inLeapYear = ecmaInLeapYear(year); 146 147 for (let i = 1; i < 12; i++) { 148 if (dayWithinYear < getFirstDayInMonth(inLeapYear, i)) { 149 return (i - 1) as byte; 150 } 151 } 152 153 return 11; 154} 155 156/** 157 * @see ECMA-262, 21.4.1.5 158 * 159 * @returns Date number (within month). 160 */ 161function ecmaDateFromTime(time: long): byte { 162 let year = ecmaYearFromTime(time); 163 let dayWithinYear = ecmaDayFromTime(time) - ecmaDayFromYear(year); 164 165 assert dayWithinYear >= 0 && dayWithinYear < dayCountInLeapYear; 166 167 let inLeapYear = ecmaInLeapYear(year); 168 169 let month: byte = 11; 170 171 for (let i = 1; i < 12; i++) { 172 if (dayWithinYear < getFirstDayInMonth(inLeapYear, i)) { 173 month = (i - 1) as byte; 174 break; 175 } 176 } 177 178 return (dayWithinYear + 1 - getFirstDayInMonth(inLeapYear, month)) as byte; 179} 180 181/** 182 * @see ECMA-262, 21.4.1.5 183 * 184 * @param time 185 * 186 * @returns Week day. 187 */ 188function ecmaWeekDay(time: long): byte { 189 let day = ecmaDayFromTime (time); 190 let weekDay = ((day + 4) % 7) as byte; 191 192 return weekDay >= 0 ? weekDay : (weekDay + 7) as byte; 193} 194 195/** 196 * @see ECMA-262, 21.4.1.5 197 * 198 * @param time 199 * 200 * @returns Week day. 201 */ 202function ecmaTimeInDayFromTime(time: long): long { 203 let day = ecmaDayFromTime(time); 204 return (time - (day * msPerDay)); 205} 206 207/** 208 * @see ECMA-262, 21.4.1.13 209 * 210 * @returns Hour component of a given time. 211 */ 212function ecmaHourFromTime(time: long): byte { 213 let timeInDay = ecmaTimeInDayFromTime(time); 214 return (timeInDay / msPerHour) as byte; 215} 216 217/** 218 * @see ECMA-262, 21.4.1.13 219 * 220 * @returns Minute component of a given time. 221 */ 222function ecmaMinFromTime(time: long): byte { 223 let timeInDay = ecmaTimeInDayFromTime(time); 224 return ((timeInDay / msPerMinute) % minutesPerHour) as byte; 225} 226 227/** 228 * @see ECMA-262, 21.4.1.13 229 * 230 * @returns Seconds component of a given time. 231 */ 232function ecmaSecFromTime(time: long): byte { 233 let timeInDay = ecmaTimeInDayFromTime(time); 234 return ((timeInDay / msPerSecond) % secondsPerMinute) as byte; 235} 236 237/** 238 * @see ECMA-262, 21.4.1.13 239 * 240 * @returns Milliseconds component of a given time. 241 */ 242function ecmaMsFromTime(time: long): short { 243 let timeInDay = ecmaTimeInDayFromTime(time); 244 return (timeInDay % msPerSecond) as short; 245} 246 247/** 248 * @see ECMA-262, 21.4.1.14 249 * 250 * @param hr 251 * 252 * @param min 253 * 254 * @param sec 255 * 256 * @param ms 257 * 258 * @returns Constructed time in milliseconds. 259 */ 260function ecmaMakeTime(hr: long, min: long, sec: long, ms: long): long { 261 return hr * msPerHour + min * msPerMinute + sec * msPerSecond + ms; 262} 263 264/** 265 * @see ECMA-262, 21.4.1.14 266 * 267 * @param hr 268 * 269 * @param min 270 * 271 * @param sec 272 * 273 * @param ms 274 * 275 * @returns Constructed time in milliseconds. 276 */ 277function ecmaMakeTime(hr: double, min: double, sec: double, ms: double): long { 278 let hh = trunc(hr) as long; 279 let mm = trunc(min) as long; 280 let ss = trunc(sec) as long; 281 let mi = trunc(ms) as long; 282 283 return ecmaMakeTime(hh, mm, ss, mi); 284} 285 286 287/** 288 * @see ECMA-262, 21.4.1.15 289 * 290 * @param year 291 * 292 * @param month 293 * 294 * @param date 295 * 296 * @returns Elapsed number of days since Unix Epoch. 297 */ 298function ecmaMakeDay(year: long, month: long, date: long): long { 299 let ym = (year + floor(month as double / 12.0 as double)) as int; 300 let mn = (month % 12) as byte; 301 302 if (mn < 0) { 303 mn += 12; 304 } 305 306 let days: long = (ecmaDayFromYear(ym) as long + getFirstDayInMonth(ecmaInLeapYear(ym), mn) as long + (date as long) - 1); 307 308 return days; 309} 310 311/** 312 * @see ECMA-262, 21.4.1.15 313 * 314 * @param year 315 * 316 * @param month 317 * 318 * @param day 319 * 320 * @returns Elapsed number of days since Unix Epoch. 321 */ 322function ecmaMakeDay(year: double, month: double, day: double): long { 323 let y = trunc(year) as long; 324 let m = trunc(month) as long; 325 let d = trunc(day) as long; 326 327 return ecmaMakeDay(y, m, d); 328} 329 330/** 331 * @see ECMA-262, 21.4.1.16 332 * 333 * @returns Elapsed number of milliseconds since Unix Epoch. 334 * 335 */ 336function ecmaMakeDate(day:long, time: long): long { 337 return day * msPerDay + time; 338} 339 340/** 341 * @see ECMA-262, 21.4.1.17 342 * 343 * @returns Elapsed number of milliceconds since Unix Epoch. 344 * 345 */ 346function ecmaTimeClip(time: long): long throws { 347 if ((time > maxDateOffset) || (time < -maxDateOffset)) { 348 throw new InvalidDate(); 349 } 350 351 return time; 352} 353 354/** 355 * Returns first day of a given year since epoch. 356 * 357 * @param year 358 * 359 * @returns day from year 360 * 361 * @see ECMA-262, 21.4.1.3, DayFromYear 362 */ 363function ecmaDayFromYear(year: int): int { 364 return (365 * (year - 1970) + 365 floor((year - 1969) / 4.0) - 366 floor((year - 1901) / 100.0) + 367 floor((year - 1601) / 400.0)) as int; 368} 369 370/** 371 * Returns first day of a given year since epoch. 372 * 373 * @param year 374 * 375 * @returns day from year 376 * 377 * @see ECMA-262, 21.4.1.3, DayFromYear 378 */ 379function ecmaTimeFromYear(year: int): long { 380 return msPerDay as long * ecmaDayFromYear(year) as long; 381} 382 383/** 384 * The leap-year function is 1 for a time within a leap year and otherwise is 0. 385 * 386 * @see ECMA-262, 21.4.1.3 387 * 388 * @returns 1 - if the year is leap 389 * 0 - otherwise 390 */ 391function ecmaInLeapYear(year: int): byte { 392 return (ecmaDaysInYear(year) - dayCountInYear) as byte; 393} 394 395/** 396 * Date JS API-compatible class 397 */ 398export final class Date { 399 /** Stored value of Date, milliseconds */ 400 private ms: long; 401 private TZOffset: long; 402 403 /** 404 * The `parseDateFromString()` static method parses a string representation of a date, 405 * and returns the number of milliseconds since January 1, 1970, 00:00:00 UTC 406 * or raises `InvalidDate` if the string is unrecognized or, in some cases, 407 * contains illegal date values (e.g. 2015-02-31). 408 * 409 * Only the @link{https://tc39.es/ecma262/#sec-date-time-string-format|ISO 8601 format} 410 * (YYYY-MM-DDTHH:mm:ss.sssZ) is explicitly specified to be supported. 411 * Other formats are implementation-defined and may not work across all browsers (targets). 412 * A library can help if many different formats are to be accommodated. 413 * 414 * @see ECMA-262, 21.4.3.2 415 * 416 * @returns A number representing the milliseconds elapsed since January 1, 1970, 00:00:00 UTC 417 * and the date obtained by parsing the given string representation of a date. 418 * If the argument doesn't represent a valid date, `InvalidDate` exception is thrown. 419 */ 420 private static parseDateFromString(dateStr: String): number { 421 let date = new Date(); 422 let sub = dateStr.substring(0, 4); 423 let val = Double.parseInt(sub, 10) as int; 424 date.setUTCFullYear(val); 425 sub = dateStr.substring(5, 7); 426 val = Double.parseInt(sub, 10) as int; 427 date.setUTCMonth(val); 428 sub = dateStr.substring(8, 10); 429 val = Double.parseInt(sub, 10) as int; 430 date.setUTCDate(val as byte); 431 sub = dateStr.substring(11, 13); 432 val = Double.parseInt(sub, 10) as int; 433 date.setUTCHours(val as byte); 434 sub = dateStr.substring(14, 16); 435 val = Double.parseInt(sub, 10) as int; 436 date.setUTCMinutes(val as byte); 437 sub = dateStr.substring(17, 19); 438 val = Double.parseInt(sub, 10) as int; 439 date.setUTCSeconds(val as byte); 440 sub = dateStr.substring(20, 23); 441 val = Double.parseInt(sub, 10) as int; 442 date.setUTCMilliseconds(val as byte); 443 return date.valueOf(); 444 } 445 /** 446 * Default constructor. 447 * 448 * @see ECMA-262, 21.4.2.1 449 * 450 * @description Initializes Date instance with current time. 451 */ 452 constructor() { 453 this.ms = Date.now() as long; 454 this.TZOffset = Date.getLocalTimezoneOffset() 455 } 456 /** 457 * `Date` constructor. 458 * 459 * @param d 460 * 461 * @see ECMA-262, 21.4.2.1 462 * 463 * @description Initializes `Date` instance with another `Date` instance. 464 */ 465 466 constructor(d: Date) { 467 this.ms = d.valueOf() as long; 468 this.TZOffset = Date.getLocalTimezoneOffset() 469 } 470 471 /** 472 * `Date` constructor. 473 * 474 * @param ms 475 * 476 * @see ECMA-262, 21.4.2.1 477 * 478 * @description Initialize `Date` instance with milliseconds given. 479 */ 480 constructor(ms: long) { 481 this.ms = ms 482 this.TZOffset = Date.getLocalTimezoneOffset() 483 } 484 485 /** 486 * `Date` constructor. 487 * 488 * @param year 489 * 490 * @param month 491 * 492 * @see ECMA-262, 21.4.2.1 493 * 494 * @description Initialize `Date` instance with year and month given. 495 */ 496 constructor(year: long, month: long) { 497 this.ms = ecmaMakeDate(ecmaMakeDay(year, month, 1 as long), ecmaMakeTime(0 as long, 0 as long, 0 as long, 0 as long)) 498 this.TZOffset = Date.getLocalTimezoneOffset() 499 } 500 501 /** 502 * `Date` constructor. 503 * 504 * @param year 505 * 506 * @param month 507 * 508 * @param day 509 * 510 * @see ECMA-262, 21.4.2.1 511 * 512 * @description Initialize `Date` instance with year, month and day given. 513 */ 514 constructor(year: long, month: long, day: long) { 515 this.ms = ecmaMakeDate(ecmaMakeDay(year, month, day), ecmaMakeTime(0 as long, 0 as long, 0 as long, 0 as long)) 516 this.TZOffset = Date.getLocalTimezoneOffset() 517 } 518 519 /** 520 * `Date` constructor. 521 * 522 * @param year 523 * 524 * @param month 525 * 526 * @param day 527 * 528 * @param hours 529 * 530 * @see ECMA-262, 21.4.2.1 531 * 532 * @description Initialize `Date` instance with year, month, day and hours given. 533 */ 534 constructor(year: long, month: long, day: long, hours: long) { 535 this.ms = ecmaMakeDate(ecmaMakeDay(year, month, day), ecmaMakeTime(hours, 0 as long, 0 as long, 0 as long)) 536 this.TZOffset = Date.getLocalTimezoneOffset() 537 } 538 539 /** 540 * `Date` constructor. 541 * 542 * @param year 543 * 544 * @param month 545 * 546 * @param day 547 * 548 * @param hours 549 * 550 * @param minutes 551 * 552 * @see ECMA-262, 21.4.2.1 553 * 554 * @description Initialize `Date` instance with year, month, day, hours and minutes given. 555 */ 556 constructor(year: long, month: long, day: long, hours: long, minutes: long) { 557 this.ms = ecmaMakeDate(ecmaMakeDay(year, month, day), ecmaMakeTime(hours, minutes, 0 as long, 0 as long)) 558 this.TZOffset = Date.getLocalTimezoneOffset() 559 } 560 561 /** 562 * `Date` constructor. 563 * 564 * @param year 565 * 566 * @param month 567 * 568 * @param day 569 * 570 * @param hours 571 * 572 * @param minutes 573 * 574 * @param seconds 575 * 576 * @see ECMA-262, 21.4.2.1 577 * 578 * @description Initialize `Date` instance with year, month, day, hours, minutes and seconds given. 579 */ 580 constructor(year: long, month: long, day: long, hours: long, minutes: long, seconds: long) { 581 this.ms = ecmaMakeDate(ecmaMakeDay(year, month, day), ecmaMakeTime(hours, minutes, seconds, 0 as long)) 582 this.TZOffset = Date.getLocalTimezoneOffset() 583 } 584 585 /** 586 * `Date` constructor. 587 * 588 * @param year 589 * 590 * @param month 591 * 592 * @param day 593 * 594 * @param hours 595 * 596 * @param minutes 597 * 598 * @param seconds 599 * 600 * @param ms 601 * 602 * @see ECMA-262, 21.4.2.1 603 * 604 * @description Initialize `Date` instance with year, month, day, hours, minutes, seconds and milliseconds given. 605 */ 606 constructor(year: long, month: long, day: long, hours: long, minutes: long, seconds: long, ms: long) { 607 this.ms = ecmaMakeDate(ecmaMakeDay(year, month, day), ecmaMakeTime(hours, minutes, seconds, ms)) 608 this.TZOffset = Date.getLocalTimezoneOffset() 609 } 610 611 /** 612 * `Date` constructor. 613 * 614 * @param ms 615 * 616 * @see ECMA-262, 21.4.2.1 617 */ 618 constructor(ms: double) { 619 this.ms = trunc(ms) as long; 620 this.TZOffset = Date.getLocalTimezoneOffset() 621 } 622 623 /** 624 * `Date` constructor. 625 * 626 * @param year 627 * 628 * @param month 629 * 630 * @see ECMA-262, 21.4.2.1 631 */ 632 constructor(year: double, month: double) { 633 this.ms = ecmaMakeDate(ecmaMakeDay(year, month, 1.0), ecmaMakeTime(0.0, 0.0, 0.0, 0.0)) 634 this.TZOffset = Date.getLocalTimezoneOffset() 635 } 636 637 /** 638 * `Date` constructor. 639 * 640 * @param year 641 * 642 * @param month 643 * 644 * @param day 645 * 646 * @see ECMA-262, 21.4.2.1 647 */ 648 constructor(year: double, month: double, day: double) { 649 this.ms = ecmaMakeDate(ecmaMakeDay(year, month, day), ecmaMakeTime(0.0, 0.0, 0.0, 0.0)) 650 this.TZOffset = Date.getLocalTimezoneOffset() 651 } 652 653 /** 654 * `Date` constructor. 655 * 656 * @param year 657 * 658 * @param month 659 * 660 * @param day 661 * 662 * @param hours 663 * 664 * @see ECMA-262, 21.4.2.1 665 */ 666 constructor(year: double, month: double, day: double, hours: double) { 667 this.ms = ecmaMakeDate(ecmaMakeDay(year, month, day), ecmaMakeTime(hours, 0.0, 0.0, 0.0)) 668 this.TZOffset = Date.getLocalTimezoneOffset() 669 } 670 671 /** 672 * `Date` constructor. 673 * 674 * @param year 675 * 676 * @param month 677 * 678 * @param day 679 * 680 * @param hours 681 * 682 * @param minutes 683 * 684 * @see ECMA-262, 21.4.2.1 685 */ 686 constructor(year: double, month: double, day: double, hours: double, minutes: double) { 687 this.ms = ecmaMakeDate(ecmaMakeDay(year, month, day), ecmaMakeTime(hours, minutes, 0.0, 0.0)) 688 this.TZOffset = Date.getLocalTimezoneOffset() 689 } 690 691 /** 692 * `Date` constructor. 693 * 694 * @param year 695 * 696 * @param month 697 * 698 * @param day 699 * 700 * @param hours 701 * 702 * @param minutes 703 * 704 * @param seconds 705 * 706 * @see ECMA-262, 21.4.2.1 707 */ 708 constructor(year: double, month: double, day: double, hours: double, minutes: double, seconds: double) { 709 this.ms = ecmaMakeDate(ecmaMakeDay(year, month, day), ecmaMakeTime(hours, minutes, seconds, 0.0)) 710 this.TZOffset = Date.getLocalTimezoneOffset() 711 } 712 713 /** 714 * `Date` constructor. 715 * 716 * @param year 717 * 718 * @param month 719 * 720 * @param day 721 * 722 * @param hours 723 * 724 * @param minutes 725 * 726 * @param seconds 727 * 728 * @param ms 729 * 730 * @see ECMA-262, 21.4.2.1 731 */ 732 constructor(year: double, month: double, day: double, hours: double, minutes: double, seconds: double, ms: double) { 733 this.ms = ecmaMakeDate(ecmaMakeDay(year, month, day), ecmaMakeTime(hours, minutes, seconds, ms)) 734 this.TZOffset = Date.getLocalTimezoneOffset() 735 } 736 737 /** 738 * The `isDateValid()` method checks if given date `ms` is maximum of ±100,000,000 739 * (one hundred million) days relative to January 1, 1970 UTC 740 * (that is, April 20, 271821 BCE ~ September 13, 275760 CE) can be represented 741 * by the standard `Date` object (equivalent to ±8,640,000,000,000,000 milliseconds). 742 */ 743 private isDateValid(ms: long): boolean { 744 return ms >= -maxDateOffset && ms <= maxDateOffset; 745 } 746 747 /** 748 * The `isDateValid()` method checks if constructed date is maximum of ±100,000,000 749 * (one hundred million) days relative to January 1, 1970 UTC 750 * (that is, April 20, 271821 BCE ~ September 13, 275760 CE) can be represented 751 * by the standard Date object (equivalent to ±8,640,000,000,000,000 milliseconds). 752 * 753 */ 754 public isDateValid(): boolean { 755 return this.isDateValid(this.ms); 756 } 757 758 /** 759 * The `valueOf()` method returns the primitive value of a `Date` object. 760 * 761 * @see ECMA-262, 21.4.4.44 762 * 763 * @returns The number of milliseconds between 1 January 1970 00:00:00 UTC and the given date. 764 * 765 * @throws InvalidDate - Throws if Date object is invalid (@link{isDateValid} is `false`). 766 */ 767 public valueOf(): number { 768 if (!this.isDateValid()) { 769 return NaN; 770 } 771 return this.ms as number; 772 } 773 774 /** 775 * The `now()` static method returns the number of milliseconds elapsed since the epoch, 776 * which is defined as the midnight at the beginning of January 1, 1970, UTC. 777 * 778 * @see ECMA-262, 21.4.3.1 779 * 780 * @returns A number representing the number of milliseconds elapsed since the epoch, 781 * which is defined as the midnight at the beginning of January 1, 1970, UTC. 782 */ 783 public static native now(): number; 784 785 /** 786 * Gets local time offset. 787 * 788 * @returns local time offset. 789 */ 790 public static native getLocalTimezoneOffset(): long; 791 792 /** 793 * Gets time zone name. 794 * 795 * @returns time zone name. 796 */ 797 public static native getTimezoneName(): String; 798 799 /** 800 * Gets locale string representation according to format. 801 * 802 * @param format 803 * 804 * @param locale 805 * 806 * @param ms 807 * 808 * @param isUTC 809 * 810 * @returns locale string in the specified format. 811 */ 812 public static native getLocaleString(format: String, locale: String, ms: long, isUTC: boolean): String; 813 814 /** 815 * Gets a string with a language-sensitive representation of the time portion of the date. 816 * 817 * @returns a language-sensitive representation of the time portion of the date. 818 */ 819 public toLocaleTimeString(): string { 820 return Date.getLocaleString("%EX", "", this.ms, false); 821 } 822 823 /** 824 * Gets a string with a language-sensitive representation of the time portion of the date with respect to locale. 825 * 826 * @param locale 827 * 828 * @returns a language-sensitive representation of the time portion of the date with respect to locale. 829 */ 830 public toLocaleTimeString(locale: string): string { 831 return Date.getLocaleString("%EX", locale, this.ms, false); 832 } 833 834 /** 835 * Gets a string with a language-sensitive representation of this date. 836 * 837 * @returns a language-sensitive representation of this date. 838 */ 839 public toLocaleString(): string { 840 return Date.getLocaleString("%Ex %EX", "", this.ms, false); 841 } 842 843 /** 844 * Gets a string with a language-sensitive representation of this date with respect to locale. 845 * 846 * @param locale 847 * 848 * @returns a language-sensitive representation of this date. 849 */ 850 public toLocaleString(locale: string): string { 851 return Date.getLocaleString("%Ex %EX", locale, this.ms, false); 852 } 853 854 /** 855 * Gets a string with a language-sensitive representation 856 * of the date portion of the specified date in the user agent's timezone. 857 * 858 * @returns a string with a language-sensitive representation 859 * of the date portion of the specified date in the user agent's timezone. 860 */ 861 public toLocaleDateString(): string { 862 return Date.getLocaleString("%Ex", "", this.ms, false); 863 } 864 865 /** 866 * Returns a string with a language-sensitive representation 867 * of the date portion of the specified date in the user agent's timezone. 868 * 869 * @returns a string with a language-sensitive representation 870 * of the date portion of the specified date in the user agent's timezone. 871 */ 872 public toLocaleDateString(locale: string): string { 873 return Date.getLocaleString("%Ex", locale, this.ms, false); 874 } 875 876 /** 877 * The `getDate()` method returns the day of the month for the specified date according to local time. 878 * 879 * @see ECMA-262, 21.4.4.2 880 * 881 * @returns An integer number, between 1 and 31, representing the day of the month for the given date according to local time. 882 */ 883 public getDate(): number { 884 let localTime = this.ms - this.TZOffset * 60 * msPerSecond; 885 let day: int = ecmaDayFromTime(localTime) - ecmaDayFromYear(ecmaYearFromTime(localTime)); 886 let inLeapYear = ecmaInLeapYear(this.getFullYear() as int); 887 let firstDay: int = getFirstDayInMonth(inLeapYear, ecmaMonthFromTime(localTime)); 888 return (day - firstDay + 1) as number; 889 } 890 891 /** 892 * Changes the day of the month of a given Date instance, based on local time. 893 * 894 * @param value new day. 895 */ 896 public setDate(value: byte): void { 897 let day = this.getDate(); 898 this.ms -= day * msPerDay; 899 this.ms += value * msPerDay; 900 } 901 902 /** 903 * Changes the day of the month of a given Date instance, based on local time. 904 * 905 * @param value new day. 906 */ 907 public setDate(value: number): number { 908 this.setDate(value as byte); 909 return this.ms as number; 910 } 911 912 /** 913 * Alias to @link{setDate} and left for compatibility with ECMA-262. 914 * 915 * @param value new day. 916 */ 917 public setDay(value: byte): void { 918 this.setDate(value); 919 } 920 921 /** 922 * Returns the day of the month (from 1 to 31) in the specified date according to universal time. 923 * 924 * @returns An integer number, between 1 and 31, representing the day of the month for the given date according to local time. 925 */ 926 public getUTCDate(): number { 927 let localTime = this.ms; 928 let day: int = ecmaDayFromTime(localTime) - ecmaDayFromYear(ecmaYearFromTime(localTime)); 929 let inLeapYear = ecmaInLeapYear(this.getFullYear() as int); 930 let firstDay: int = getFirstDayInMonth(inLeapYear, ecmaMonthFromTime(localTime)); 931 return (day - firstDay) as number; 932 } 933 934 /** 935 * Changes the day of the month of a given Date instance, based on UTC time. 936 * 937 * @param value new day. 938 */ 939 public setUTCDate(value: byte): void { 940 let day = this.getUTCDate() as byte; 941 this.ms -= day * msPerDay; 942 this.ms += value * msPerDay; 943 } 944 945 /** 946 * Changes the day of the month of a given Date instance, based on UTC time. 947 * 948 * @param value new day. 949 */ 950 public setUTCDate(value: number): number { 951 this.setUTCDate(value as byte); 952 return this.ms as number; 953 } 954 955 /** 956 * Changes the day of the month of a given Date instance, based on UTC time. 957 * 958 * @param value new day. 959 */ 960 public setUTCDay(value: byte): void { 961 this.setUTCDate(value); 962 } 963 964 /** 965 * Changes the day of the month of a given Date instance, based on UTC time. 966 * 967 * @param value new day. 968 */ 969 public setUTCDay(value: number): number { 970 this.setUTCDate(value); 971 return this.ms as number; 972 } 973 974 /** 975 * Returns the day of the week for the specified date according to local time, 976 * where 0 represents Sunday. For the day of the month, see @link{getDayOfMonth}. 977 * 978 * @see ECMA-262, 21.4.4.3 979 * 980 * @returns An integer number, between 0 and 6, corresponding to the day of the week 981 * for the given date, according to local time: 0 for Sunday, 1 for Monday, 2 for Tuesday, and so on. 982 */ 983 public getDay(): number { 984 return ecmaWeekDay(this.ms - this.TZOffset * 60 * msPerSecond) as number; 985 } 986 987 /** 988 * Returns the day of the week in the specified date according to universal time, where 0 represents Sunday. 989 * 990 * @returns An integer number, between 0 and 6, corresponding to the day of the week 991 * for the given date, according to local time: 0 for Sunday, 1 for Monday, 2 for Tuesday, and so on. 992 */ 993 public getUTCDay(): number { 994 return ecmaWeekDay(this.ms) as number; 995 } 996 997 /** 998 * Returns the year of the specified date according to local time. 999 * 1000 * @see ECMA-262, 21.4.4.4 1001 * deprecated 1002 * @note This function is an alias to @link{getFullYear} and left for compatibility with ECMA-262. 1003 * 1004 * @returns year 1005 */ 1006 public getYear(): int { 1007 return this.getFullYear() as int; 1008 } 1009 1010 /** 1011 * Returns the year of the specified date according to local time. 1012 * 1013 * @returns A year of the specified date according to local time. 1014 * 1015 * @description The value returned by `getUTCFullYear()` is an absolute number. 1016 * For dates between the years 1000 and 9999, `getUTCFullYear()` returns a four-digit number, 1017 * for example, 1995. Use this function to make sure a year is compliant with years after 2000. 1018 * 1019 * @returns year 1020 */ 1021 public getUTCFullYear(): number { 1022 return ecmaYearFromTime(this.ms) as number; 1023 } 1024 1025 /** 1026 * Returns the year of the specified date according to local time. 1027 * 1028 * @see ECMA-262, 21.4.4.4 1029 * 1030 * @returns A number corresponding to the year of the given date, according to local time. 1031 * 1032 * @description The value returned by `getFullYear()` is an absolute number. 1033 * For dates between the years 1000 and 9999, `getFullYear()` returns a four-digit number, 1034 * for example, 1995. Use this function to make sure a year is compliant with years after 2000. 1035 * 1036 * @example 1037 * ```sts 1038 * const today = new Date(); 1039 * const year = today.getYearFull(); 1040 * ``` 1041 */ 1042 public getFullYear(): number { 1043 let localTime = this.ms - this.TZOffset * 60 * msPerSecond; 1044 return ecmaYearFromTime(localTime) as number; 1045 } 1046 1047 /** 1048 * Sets the full year for a specified date according to universal time. 1049 * 1050 * @param value new year 1051 */ 1052 public setUTCFullYear(value: number, month?: Number, date?: Number): number { 1053 this.setUTCFullYear(value as int); 1054 if (month !== undefined) { 1055 this.setUTCMonth(month?.intValue()); 1056 } 1057 if (date !== undefined) { 1058 this.setUTCDate(date?.byteValue()); 1059 } 1060 return this.ms as number; 1061 } 1062 1063 /** 1064 * Sets the full year for a specified date according to universal time. 1065 * 1066 * @param value new year 1067 */ 1068 public setUTCFullYear(value: int): void { 1069 let year = ecmaYearFromTime(this.ms); 1070 this.ms -= ecmaDayFromYear(year) * msPerDay as long; 1071 this.ms += ecmaDayFromYear(value) * msPerDay as long; 1072 } 1073 1074 /** 1075 * This function is an alias to @link{setFullYear} and left for compatibility with ECMA-262. 1076 * 1077 * @param value new year 1078 */ 1079 public setYear(value: number): void { 1080 this.setYear(value as int) 1081 } 1082 1083 /** 1084 * This function is an alias to @link{setFullYear} and left for compatibility with ECMA-262. 1085 * 1086 * @param value new year 1087 */ 1088 public setYear(value: int): void { 1089 this.setFullYear(value); 1090 } 1091 1092 /** 1093 * Sets the full year for a specified date according to local time. 1094 * 1095 * @param value new year 1096 */ 1097 public setFullYear(value: number, month?: Number, date?: Number): number { 1098 this.setFullYear(value as int); 1099 if (month !== undefined) { 1100 this.setMonth(month?.intValue()); 1101 } 1102 if (date !== undefined) { 1103 this.setDate(date?.byteValue()); 1104 } 1105 return this.ms as number; 1106 } 1107 1108 /** 1109 * Sets the full year for a specified date according to local time. 1110 * 1111 * @param value new year 1112 */ 1113 public setFullYear(value: int): void { 1114 let year = ecmaYearFromTime(this.ms - this.TZOffset * 60 * msPerSecond); 1115 this.ms -= ecmaDayFromYear(year) * msPerDay as long; 1116 this.ms += ecmaDayFromYear(value) * msPerDay as long; 1117 } 1118 1119 /** 1120 * Returns the hour for the specified date, according to local time. 1121 * 1122 * @see ECMA-262, 21.4.4.5 1123 * 1124 * @returns An integer number, between 0 and 23, representing the hour for the given date according to local time. 1125 * 1126 * @example 1127 * ```sts 1128 * const today = new Date(); 1129 * const hours = today.getHour(); 1130 * ``` 1131 */ 1132 public getHours(): number { 1133 let localTime = this.ms - this.TZOffset * 60 * msPerSecond; 1134 return ecmaHourFromTime(localTime) as number; 1135 } 1136 1137 /** 1138 * Returns the hours in the specified date according to universal time. 1139 * 1140 * @returns An integer number, between 0 and 23, representing the hour for the given date according to UTC time. 1141 */ 1142 public getUTCHours(): number { 1143 return ecmaHourFromTime(this.ms) as number; 1144 } 1145 1146 /** 1147 * Sets the hours for a specified date according to local time. 1148 * 1149 * @param value new hours 1150 */ 1151 public setHours(value: byte): void { 1152 assert value >= 0 && value <= 23; 1153 let hours = ecmaHourFromTime(this.ms - this.TZOffset * 60 * msPerSecond); 1154 this.ms -= msPerHour * hours; 1155 this.ms += msPerHour * value; 1156 } 1157 1158 /** 1159 * Sets the hours for a specified date according to local time. 1160 * 1161 * @param value new hours 1162 */ 1163 public setHours(value: number, min?: Number, sec?: Number, ms?: Number): number { 1164 this.setHours(value as byte); 1165 if (min !== undefined) { 1166 this.setMinutes(min?.byteValue()); 1167 } 1168 if (sec !== undefined) { 1169 this.setSeconds(sec?.byteValue()); 1170 } 1171 if (ms !== undefined) { 1172 this.setMilliseconds(ms?.shortValue()); 1173 } 1174 return this.ms as number; 1175 } 1176 1177 /** 1178 * Sets the hour for a specified date according to universal time. 1179 * 1180 * @param value new hours 1181 */ 1182 public setUTCHours(value: byte): void { 1183 assert value >= 0 && value <= 23; 1184 let hours = ecmaHourFromTime(this.ms); 1185 this.ms -= msPerHour * hours; 1186 this.ms += msPerHour * value; 1187 } 1188 1189 /** 1190 * Sets the hour for a specified date according to universal time. 1191 * 1192 * @param value new hours 1193 */ 1194 public setUTCHours(value: number, min?: Number, sec?: Number, ms?: Number): number { 1195 this.setUTCHours(value as byte); 1196 if (min !== undefined) { 1197 this.setUTCMinutes(min?.byteValue()); 1198 } 1199 if (sec !== undefined) { 1200 this.setUTCSeconds(sec?.byteValue()); 1201 } 1202 if (ms !== undefined) { 1203 this.setUTCMilliseconds(ms?.shortValue()); 1204 } 1205 return this.ms as number; 1206 } 1207 1208 /** 1209 * Returns the milliseconds in the specified date according to local time. 1210 * 1211 * @see ECMA-262, 21.4.4.6 1212 * 1213 * @returns A number between 0 and 999 representing the milliseconds for the given date according to local time. 1214 * 1215 * @example 1216 * ```sts 1217 * const today = new Date(); 1218 * const milliseconds = today.getMilliseconds(); 1219 * ``` 1220 */ 1221 public getMilliseconds(): number { 1222 let localTime = this.ms - this.TZOffset * 60 * msPerSecond; 1223 return ecmaMsFromTime(localTime) as number; 1224 } 1225 1226 /** 1227 * Returns the number of milliseconds elapsed since the epoch, 1228 * which is defined as the midnight at the beginning of January 1, 1970, UTC. 1229 * 1230 * @param d to be converted to milliseconds. 1231 * 1232 * @see ECMA-262, 21.4.3.1 1233 * 1234 * @returns A number representing the number of milliseconds elapsed since the epoch, 1235 * which is defined as the midnight at the beginning of January 1, 1970, UTC. 1236 */ 1237 public static UTC(d: Date): long { 1238 return d.valueOf() as long; 1239 } 1240 1241 /** 1242 * Returns the number of milliseconds elapsed since the epoch, 1243 * which is defined as the midnight at the beginning of January 1, 1970, UTC. 1244 * 1245 * @param year to be converted to milliseconds. 1246 * 1247 * @returns A number representing the number of milliseconds elapsed since the epoch, 1248 * which is defined as the midnight at the beginning of January 1, 1970, UTC. 1249 */ 1250 public static UTC(year: long): long { 1251 return ecmaMakeDate(ecmaMakeDay(year, 0 as long, 1 as long), ecmaMakeTime(0 as long, 0 as long, 0 as long, 0 as long)) 1252 } 1253 1254 /** 1255 * Returns the number of milliseconds elapsed since the epoch, 1256 * which is defined as the midnight at the beginning of January 1, 1970, UTC. 1257 * 1258 * @param year to be converted to milliseconds. 1259 * 1260 * @param month to be converted to milliseconds. 1261 * 1262 * @returns A number representing the number of milliseconds elapsed since the epoch, 1263 * which is defined as the midnight at the beginning of January 1, 1970, UTC. 1264 */ 1265 public static UTC(year: long, month: long): long { 1266 return ecmaMakeDate(ecmaMakeDay(year, month, 1 as long), ecmaMakeTime(0 as long, 0 as long, 0 as long, 0 as long)) 1267 } 1268 1269 /** 1270 * Returns the number of milliseconds elapsed since the epoch, 1271 * which is defined as the midnight at the beginning of January 1, 1970, UTC. 1272 * 1273 * @param year to be converted to milliseconds. 1274 * 1275 * @param month to be converted to milliseconds. 1276 * 1277 * @param day to be converted to milliseconds. 1278 * 1279 * @returns A number representing the number of milliseconds elapsed since the epoch, 1280 * which is defined as the midnight at the beginning of January 1, 1970, UTC. 1281 */ 1282 public static UTC(year: long, month: long, day: long): long { 1283 return ecmaMakeDate(ecmaMakeDay(year, month, day), ecmaMakeTime(0 as long, 0 as long, 0 as long, 0 as long)) 1284 } 1285 1286 /** 1287 * Returns the number of milliseconds elapsed since the epoch, 1288 * which is defined as the midnight at the beginning of January 1, 1970, UTC. 1289 * 1290 * @param year to be converted to milliseconds. 1291 * 1292 * @param month to be converted to milliseconds. 1293 * 1294 * @param day to be converted to milliseconds. 1295 * 1296 * @param hours to be converted to milliseconds. 1297 * 1298 * @returns A number representing the number of milliseconds elapsed since the epoch, 1299 * which is defined as the midnight at the beginning of January 1, 1970, UTC. 1300 */ 1301 public static UTC(year: long, month: long, day: long, hours: long): long { 1302 return ecmaMakeDate(ecmaMakeDay(year, month, day), ecmaMakeTime(hours, 0 as long, 0 as long, 0 as long)) 1303 } 1304 1305 /** 1306 * Returns the number of milliseconds elapsed since the epoch, 1307 * which is defined as the midnight at the beginning of January 1, 1970, UTC. 1308 * 1309 * @param year to be converted to milliseconds. 1310 * 1311 * @param month to be converted to milliseconds. 1312 * 1313 * @param day to be converted to milliseconds. 1314 * 1315 * @param hours to be converted to milliseconds. 1316 * 1317 * @param minutes to be converted to milliseconds. 1318 * 1319 * @returns A number representing the number of milliseconds elapsed since the epoch, 1320 * which is defined as the midnight at the beginning of January 1, 1970, UTC. 1321 */ 1322 public static UTC(year: long, month: long, day: long, hours: long, minutes: long): long { 1323 return ecmaMakeDate(ecmaMakeDay(year, month, day), ecmaMakeTime(hours, minutes, 0 as long, 0 as long)) 1324 } 1325 1326 /** 1327 * Returns the number of milliseconds elapsed since the epoch, 1328 * which is defined as the midnight at the beginning of January 1, 1970, UTC. 1329 * 1330 * @param year to be converted to milliseconds. 1331 * 1332 * @param month to be converted to milliseconds. 1333 * 1334 * @param day to be converted to milliseconds. 1335 * 1336 * @param hours to be converted to milliseconds. 1337 * 1338 * @param minutes to be converted to milliseconds. 1339 * 1340 * @param seconds to be converted to milliseconds. 1341 * 1342 * @returns A number representing the number of milliseconds elapsed since the epoch, 1343 * which is defined as the midnight at the beginning of January 1, 1970, UTC. 1344 */ 1345 public static UTC(year: long, month: long, day: long, hours: long, minutes: long, seconds: long): long { 1346 return ecmaMakeDate(ecmaMakeDay(year, month, day), ecmaMakeTime(hours, minutes, seconds, 0 as long)) 1347 } 1348 1349 /** 1350 * Returns the number of milliseconds elapsed since the epoch, 1351 * which is defined as the midnight at the beginning of January 1, 1970, UTC. 1352 * 1353 * @param year to be converted to milliseconds. 1354 * 1355 * @param month to be converted to milliseconds. 1356 * 1357 * @param day to be converted to milliseconds. 1358 * 1359 * @param hours to be converted to milliseconds. 1360 * 1361 * @param minutes to be converted to milliseconds. 1362 * 1363 * @param seconds to be converted to milliseconds. 1364 * 1365 * @param ms to be converted to milliseconds. 1366 * 1367 * @returns A number representing the number of milliseconds elapsed since the epoch, 1368 * which is defined as the midnight at the beginning of January 1, 1970, UTC. 1369 */ 1370 public static UTC(year: long, month: long, day: long, hours: long, minutes: long, seconds: long, ms: long): long { 1371 return ecmaMakeDate(ecmaMakeDay(year, month, day), ecmaMakeTime(hours, minutes, seconds, ms)) 1372 } 1373 1374 /** 1375 * Returns the number of milliseconds elapsed since the epoch, 1376 * which is defined as the midnight at the beginning of January 1, 1970, UTC. 1377 * 1378 * @param year to be converted to milliseconds. 1379 * 1380 * @returns A number representing the number of milliseconds elapsed since the epoch, 1381 * which is defined as the midnight at the beginning of January 1, 1970, UTC. 1382 */ 1383 public static UTC(year: number): number { 1384 return ecmaMakeDate(ecmaMakeDay(year, 0.0, 1.0), ecmaMakeTime(0.0, 0.0, 0.0, 0.0)) as number 1385 } 1386 1387 /** 1388 * Returns the number of milliseconds elapsed since the epoch, 1389 * which is defined as the midnight at the beginning of January 1, 1970, UTC. 1390 * 1391 * @param year to be converted to milliseconds. 1392 * 1393 * @param month to be converted to milliseconds. 1394 * 1395 * @param day to be converted to milliseconds. 1396 * 1397 * @param hours to be converted to milliseconds. 1398 * 1399 * @param minutes to be converted to milliseconds. 1400 * 1401 * @param seconds to be converted to milliseconds. 1402 * 1403 * @param ms to be converted to milliseconds. 1404 * 1405 * @returns A number representing the number of milliseconds elapsed since the epoch, 1406 * which is defined as the midnight at the beginning of January 1, 1970, UTC. 1407 */ 1408 public static UTC(year: number, month: number, day?: Number, hours?: Number, minutes?: Number, seconds?: Number, ms?: Number): number { 1409 let defaultDay = day !== undefined ? day.valueOf() : 1.0; 1410 let defaultHours = hours !== undefined ? hours.valueOf() : 0.0; 1411 let defaultMinutes = minutes !== undefined ? minutes.valueOf() : 0.0; 1412 let defaultSeconds = seconds !== undefined ? seconds.valueOf() : 0.0; 1413 let defaultMS = ms !== undefined ? ms.valueOf() : 0.0; 1414 return ecmaMakeDate(ecmaMakeDay(year, month, defaultDay), ecmaMakeTime(defaultHours, defaultMinutes, defaultSeconds, defaultMS)) as number; 1415 } 1416 1417 /** 1418 * Returns the milliseconds portion of the time object's value according to universal time. 1419 * 1420 * @returns the milliseconds portion of the time object's value according to universal time. 1421 */ 1422 public getUTCMilliseconds(): number { 1423 let localTime = this.ms; 1424 return ecmaMsFromTime(localTime) as number; 1425 } 1426 1427 /** 1428 * Sets the milliseconds for a specified date according to local time. 1429 * 1430 * @param value new ms 1431 */ 1432 public setMilliseconds(value: short): void { 1433 let ms = ecmaMsFromTime(this.ms - this.TZOffset * 60 * msPerSecond); 1434 this.ms -= ms; 1435 this.ms += value; 1436 } 1437 1438 /** 1439 * Sets the milliseconds for a specified date according to local time. 1440 * 1441 * @param value new ms 1442 */ 1443 public setMilliseconds(value: number): number { 1444 this.setMilliseconds(value as short); 1445 return this.ms as number; 1446 } 1447 1448 /** 1449 * Sets the milliseconds for a specified date according to universal time. 1450 * 1451 * @param value new ms 1452 */ 1453 public setUTCMilliseconds(value: short): void { 1454 let ms = ecmaMsFromTime(this.ms); 1455 this.ms -= ms; 1456 this.ms += value; 1457 } 1458 1459 /** 1460 * Sets the milliseconds for a specified date according to universal time. 1461 * 1462 * @param value new ms 1463 */ 1464 public setUTCMilliseconds(value: number): number { 1465 this.setUTCMilliseconds(value as short); 1466 return this.ms as number; 1467 } 1468 1469 /** 1470 * Returns the seconds in the specified date according to local time. 1471 * 1472 * @see ECMA-262, 21.4.4.9 1473 * 1474 * @returns An integer number, between 0 and 59, representing the seconds in the given date according to local time. 1475 * 1476 * @example 1477 * ```sts 1478 * const today = new Date(); 1479 * const seconds = today.getSeconds(); 1480 * ``` 1481 */ 1482 public getSeconds(): number { 1483 let localTime = this.ms - this.TZOffset * 60 * msPerSecond; 1484 return ecmaSecFromTime(localTime) as number; 1485 } 1486 1487 /** 1488 * Returns the seconds in the specified date according to universal time. 1489 * 1490 * @returns the seconds in the specified date according to universal time. 1491 */ 1492 public getUTCSeconds(): number { 1493 return ecmaSecFromTime(this.ms) as number; 1494 } 1495 1496 /** 1497 * Sets the seconds for a specified date according to local time. 1498 * 1499 * @param value new seconds 1500 */ 1501 public setSeconds(value: number, ms?: Number): number { 1502 this.setSeconds(value as byte); 1503 if (ms !== undefined) { 1504 this.setMilliseconds(ms?.shortValue()); 1505 } 1506 return this.ms as number; 1507 } 1508 1509 /** 1510 * Sets the seconds for a specified date according to local time. 1511 * 1512 * @param value new seconds 1513 */ 1514 public setSeconds(value: byte): void { 1515 assert value >= 0 && value < 60; 1516 let sec = ecmaSecFromTime(this.ms - this.TZOffset * 60 * msPerSecond); 1517 this.ms -= sec * msPerSecond; 1518 this.ms += value * msPerSecond; 1519 } 1520 1521 /** 1522 * Sets the seconds for a specified date according to universal time. 1523 * 1524 * @param value new seconds 1525 */ 1526 public setUTCSeconds(value: byte): void { 1527 assert value >= 0 && value < 60; 1528 let sec = ecmaSecFromTime(this.ms); 1529 this.ms -= sec * msPerSecond; 1530 this.ms += value * msPerSecond; 1531 } 1532 1533 /** 1534 * Sets the seconds for a specified date according to universal time. 1535 * 1536 * @param value new seconds 1537 */ 1538 public setUTCSeconds(value: number, ms?: Number): number { 1539 this.setUTCSeconds(value as byte); 1540 if (ms !== undefined) { 1541 this.setUTCMilliseconds(ms?.shortValue()); 1542 } 1543 return this.ms as number; 1544 } 1545 1546 /** 1547 * Returns the minutes in the specified date according to local time. 1548 * 1549 * @see ECMA-262, 21.4.4.7 1550 * 1551 * @returns An integer number, between 0 and 59, representing the minutes in the given date according to local time. 1552 * 1553 * @example 1554 * ```sts 1555 * const today = new Date(); 1556 * const minutes = today.getMinutes(); 1557 * ``` 1558 */ 1559 public getMinutes(): number { 1560 let localTime = this.ms - this.TZOffset * 60 * msPerSecond; 1561 return ecmaMinFromTime(localTime) as number; 1562 } 1563 1564 /** 1565 * Sets the minutes for a specified date according to universal time. 1566 * 1567 * @param value new minutes 1568 */ 1569 public setUTCMinutes(value: byte): void { 1570 assert value >= 0 && value < 60; 1571 let min = ecmaMinFromTime(this.ms); 1572 this.ms -= min * msPerMinute; 1573 this.ms += value * msPerMinute; 1574 } 1575 1576 /** 1577 * Sets the minutes for a specified date according to universal time. 1578 * 1579 * @param value new minutes 1580 */ 1581 public setUTCMinutes(value: number, sec?: Number, ms?: Number): number { 1582 this.setUTCMinutes(value as byte); 1583 if (sec !== undefined) { 1584 this.setUTCSeconds(sec?.byteValue()); 1585 } 1586 if (ms !== undefined) { 1587 this.setUTCMilliseconds(ms?.shortValue()); 1588 } 1589 return this.ms as number; 1590 } 1591 1592 /** 1593 * Returns the minutes in the specified date according to universal time. 1594 * 1595 * @returns the minutes in the specified date according to universal time. 1596 */ 1597 public getUTCMinutes(): number { 1598 return ecmaMinFromTime(this.ms) as number; 1599 } 1600 1601 /** 1602 * Sets the minutes for a specified date according to local time. 1603 * 1604 * @param value new minutes 1605 */ 1606 public setMinutes(value: byte): void { 1607 assert value >= 0 && value < 60; 1608 let min = ecmaMinFromTime(this.ms - this.TZOffset * 60 * msPerSecond); 1609 this.ms -= min * msPerMinute; 1610 this.ms += value * msPerMinute; 1611 } 1612 1613 /** 1614 * Sets the minutes for a specified date according to local time. 1615 * 1616 * @param value new minutes 1617 */ 1618 public setMinutes(value: number, sec?: Number, ms?: Number): number { 1619 this.setMinutes(value as byte); 1620 if (sec !== undefined) { 1621 this.setSeconds(sec?.byteValue()); 1622 } 1623 if (ms !== undefined) { 1624 this.setMilliseconds(ms.shortValue()); 1625 } 1626 return this.ms as number; 1627 } 1628 1629 /** 1630 * Returns the month in the specified date according to local time, 1631 * as a zero-based value (where zero indicates the first month of the year). 1632 * 1633 * @see ECMA-262, 21.4.4.8 1634 * 1635 * @returns An integer number, between 0 and 11, representing the month in the given date according to local time. 1636 * 0 corresponds to January, 1 to February, and so on. 1637 * 1638 * @example 1639 * ```sts 1640 * const today = new Date(); 1641 * const month = today.getMonth(); 1642 * ``` 1643 */ 1644 public getMonth(): number { 1645 let localTime = this.ms - this.TZOffset * 60 * msPerSecond; 1646 return ecmaMonthFromTime(localTime) as number; 1647 } 1648 1649 /** 1650 * Returns the month of the specified date according to universal time, as a zero-based value (where zero indicates the first month of the year). 1651 * 1652 * @returns An integer number, between 0 and 11, representing the month in the given date according to UTC time. 1653 * 0 corresponds to January, 1 to February, and so on. 1654 */ 1655 public getUTCMonth(): number { 1656 return ecmaMonthFromTime(this.ms) as number; 1657 } 1658 1659 /** 1660 * Sets the month for a specified date according to the currently set year. 1661 * 1662 * @param month new month 1663 */ 1664 public setMonth(month: number, date?: Number): number { 1665 this.setMonth(month as int); 1666 if (date !== undefined) { 1667 this.setDate(date.byteValue()); 1668 } 1669 return this.ms as number; 1670 } 1671 1672 /** 1673 * Sets the month for a specified date according to the currently set year. 1674 * 1675 * @param month new month 1676 */ 1677 public setMonth(month: int): void { 1678 let inLeapYear = ecmaInLeapYear(this.getFullYear() as int); 1679 let daysNow: int = getFirstDayInMonth(inLeapYear, ecmaMonthFromTime(this.ms - this.TZOffset * 60 * msPerSecond)); 1680 let daysNew: int = getFirstDayInMonth(inLeapYear, month); 1681 this.ms -= daysNow * msPerDay; 1682 this.ms += daysNew * msPerDay; 1683 } 1684 1685 /** 1686 * Sets the month for a specified date according to universal time. 1687 * 1688 * @param month new month 1689 */ 1690 public setUTCMonth(month: number, date?: Number): number { 1691 this.setUTCMonth(month as int); 1692 if (date !== undefined) { 1693 this.setUTCDate(date?.byteValue()); 1694 } 1695 return this.ms as number; 1696 } 1697 1698 /** 1699 * Sets the month for a specified date according to universal time. 1700 * 1701 * @param month new month 1702 */ 1703 public setUTCMonth(month: int): void { 1704 let inLeapYear = ecmaInLeapYear(this.getFullYear() as int); 1705 let daysNow: int = getFirstDayInMonth(inLeapYear, ecmaMonthFromTime(this.ms)); 1706 let daysNew: int = getFirstDayInMonth(inLeapYear, month); 1707 this.ms -= daysNow * msPerDay; 1708 this.ms += daysNew * msPerDay; 1709 } 1710 1711 /** 1712 * Returns the number of milliseconds since the epoch, 1713 * which is defined as the midnight at the beginning of January 1, 1970, UTC. 1714 * 1715 * @see ECMA-262, 21.4.4.10 1716 * 1717 * @returns A number representing the milliseconds elapsed between 1 January 1970 00:00:00 UTC and the given date. 1718 */ 1719 public getTime(): number { 1720 return this.valueOf(); 1721 } 1722 1723 /** 1724 * Sets the number of milliseconds since the epoch, 1725 * which is defined as the midnight at the beginning of January 1, 1970, UTC. 1726 * 1727 * @param value new ms 1728 * 1729 * @see ECMA-262, 21.4.4.10 1730 * 1731 * @returns A number representing the milliseconds elapsed between 1 January 1970 00:00:00 UTC and the given date. 1732 */ 1733 public setTime(value: long): void { 1734 this.ms = value; 1735 } 1736 1737 /** 1738 * Sets the number of milliseconds since the epoch, 1739 * which is defined as the midnight at the beginning of January 1, 1970, UTC. 1740 * 1741 * @param value new ms 1742 * 1743 * @see ECMA-262, 21.4.4.10 1744 * 1745 * @returns A number representing the milliseconds elapsed between 1 January 1970 00:00:00 UTC and the given date. 1746 */ 1747 public setTime(value: number): number { 1748 this.setTime(value as long); 1749 return this.ms as number; 1750 } 1751 1752 /** 1753 * Parses a string representation of a date, 1754 * and returns the number of milliseconds since January 1, 1970, 00:00:00 UTC 1755 * or raises `InvalidDate` if the string is unrecognized or, in some cases, 1756 * contains illegal date values (e.g. 2015-02-31). 1757 * 1758 * Only the @link{https://tc39.es/ecma262/#sec-date-time-string-format|ISO 8601 format} 1759 * (YYYY-MM-DDTHH:mm:ss.sssZ) is explicitly specified to be supported. 1760 * Other formats are implementation-defined and may not work across all browsers (targets). 1761 * A library can help if many different formats are to be accommodated. 1762 * 1763 * @param dateStr to be parsed 1764 * 1765 * @see ECMA-262, 21.4.3.2 1766 * 1767 * @returns A number representing the milliseconds elapsed since January 1, 1970, 00:00:00 UTC 1768 * and the date obtained by parsing the given string representation of a date. 1769 * If the argument doesn't represent a valid date, `InvalidDate` exception is thrown. 1770 */ 1771 public static parse(dateStr: string): number { 1772 return Date.parseDateFromString(dateStr) as number; 1773 } 1774 1775 /** 1776 * Returns the difference, in minutes, between a date as 1777 * evaluated in the UTC time zone, and the same date as evaluated in the local time zone. 1778 * 1779 * @returns the difference, in minutes, between a date as 1780 * evaluated in the UTC time zone, and the same date as evaluated in the local time zone. 1781 */ 1782 public getTimezoneOffset(): number { 1783 return this.TZOffset as number; 1784 } 1785 1786 /** 1787 * Sets the difference, in minutes, between a date as 1788 * evaluated in the UTC time zone, and the same date as evaluated in the local time zone. 1789 * 1790 * @param value new timezone offset 1791 */ 1792 public setTimezoneOffset(value: number): number { 1793 return this.setTimezoneOffset(value as int) as number 1794 } 1795 1796 /** 1797 * Sets the difference, in minutes, between a date as 1798 * evaluated in the UTC time zone, and the same date as evaluated in the local time zone. 1799 * 1800 * @param value new timezone offset 1801 */ 1802 public setTimezoneOffset(value: int): long { 1803 this.TZOffset = value; 1804 } 1805 1806 /** 1807 * Returns a string in simplified extended ISO format (ISO 8601), 1808 * which is always 24 or 27 characters long (YYYY-MM-DDTHH:mm:ss.sssZ or 1809 * ±YYYYYY-MM-DDTHH:mm:ss.sssZ, respectively). The timezone is always zero UTC offset, 1810 * as denoted by the suffix Z. 1811 * 1812 * @see ECMA-262, 21.4.4.36 1813 * 1814 * @returns A string representing the given date in the ISO 8601 format according to universal time. 1815 * It's the same format as the one required to be recognized by @link{parse()}. 1816 * 1817 * @example 1818 * ```sts 1819 * const today = new Date(); 1820 * console.println(today.toISOString()); // Returns 2023-02-05T14:48:00.000Z 1821 * ``` 1822 */ 1823 public toISOString(): string { 1824 let sb = new StringBuilder(); 1825 let year = this.getUTCFullYear(); 1826 if(year < 0 || year > 9999) { 1827 if(year < 0) { 1828 sb.append("-"); 1829 } 1830 year = abs(year) as int; 1831 sb.append(year / 100000); 1832 sb.append((year / 10000) % 10); 1833 } 1834 sb.append((year / 1000) % 10); 1835 sb.append((year / 100) % 10); 1836 sb.append((year / 10) % 10); 1837 sb.append(year % 10); 1838 sb.append("-"); 1839 let month = this.getUTCMonth(); 1840 if(month < 10){ 1841 sb.append("0"); 1842 } 1843 sb.append(month + 1); 1844 sb.append("-"); 1845 let day = this.getUTCDate(); 1846 if(day < 10){ 1847 sb.append("0"); 1848 } 1849 sb.append(day); 1850 sb.append("T"); 1851 let h = this.getUTCHours(); 1852 if(h < 10) { 1853 sb.append("0"); 1854 } 1855 sb.append(h); 1856 sb.append(":"); 1857 let m = this.getUTCMinutes(); 1858 if(m < 10) { 1859 sb.append("0"); 1860 } 1861 sb.append(m); 1862 sb.append(":"); 1863 let s = this.getUTCSeconds(); 1864 if(s < 10) { 1865 sb.append("0"); 1866 } 1867 sb.append(s); 1868 sb.append("."); 1869 let ms = this.getUTCMilliseconds(); 1870 sb.append(ms / 100); 1871 sb.append((ms / 10) % 10); 1872 sb.append(ms % 10); 1873 sb.append("Z"); 1874 return sb.toString(); 1875 } 1876 1877 /** 1878 * Returns a string representation of the Date object. 1879 * 1880 * @returns JSON representation of the current instance 1881 */ 1882 public toJSON(): string { 1883 return this.toISOString(); 1884 } 1885 1886 /** 1887 * Returns the time portion of a `Date` object interpreted in the local timezone in English. 1888 * 1889 * @see ECMA-262, 21.4.4.42 1890 * 1891 * @returns A string representing the time portion of the given date in human-readable form in English. 1892 * 1893 * @example 1894 * ``` 1895 * let d = new Date(1979.0, 9.0, 27.0, 13.0, 12.8, 57.0, 444.1); 1896 * console.println(d.toTimeString()); // 13:12:57 GMT 1897 * ``` 1898 */ 1899 public toTimeString(): string { 1900 return this.timeString() + " " + this.timeZoneString(); 1901 } 1902 1903 /** 1904 * Returns string representation 1905 */ 1906 private timeString(): String { 1907 if (!this.isDateValid()) { 1908 throw new Error("Invalid Date"); 1909 } 1910 1911 let sb = new StringBuilder(); 1912 let h = this.getHours(); 1913 if (h < 10) { 1914 sb.append("0"); 1915 } 1916 sb.append(h); 1917 sb.append(":"); 1918 let m = this.getMinutes(); 1919 if (m < 10) { 1920 sb.append("0"); 1921 } 1922 sb.append(m); 1923 sb.append(":"); 1924 let s = this.getSeconds(); 1925 if (s < 10) { 1926 sb.append("0"); 1927 } 1928 sb.append(s); 1929 return sb.toString(); 1930 } 1931 1932 /** 1933 * Returns the date portion of a `Date` object interpreted in the local timezone in English. 1934 * 1935 * @see ECMA-262, 21.4.4.35 1936 * 1937 * @returns A string representing the date portion of the given Date object in human-readable form in English. 1938 * 1939 * @example 1940 * ``` 1941 * let d = new Date(1979.0, 9.0, 27.0, 13.0, 12.8, 57.0, 444.1); 1942 * console.println(d.toDateString()); // Sat Oct 27 1979 1943 * ``` 1944 */ 1945 public toDateString(): string { 1946 return this.dateString(); 1947 } 1948 1949 /** 1950 * Returns a string representation 1951 */ 1952 private dateString(): String { 1953 if (!this.isDateValid()) { 1954 throw new Error("Invalid Date"); 1955 } 1956 1957 let sb = new StringBuilder(); 1958 sb.append(dayNames[this.getDay() as int]); 1959 sb.append(" "); 1960 sb.append(monthNames[this.getMonth() as int]); 1961 sb.append(" "); 1962 let d = this.getDate(); 1963 if (d < 10) { 1964 sb.append("0"); 1965 } 1966 sb.append(d); 1967 sb.append(" "); 1968 let y = this.getFullYear(); 1969 if (y < 0) { 1970 sb.append("-"); 1971 } 1972 if (abs(y) < 1000) { 1973 sb.append("0"); 1974 } 1975 if (abs(y) < 100) { 1976 sb.append("0"); 1977 } 1978 if (abs(y) < 10) { 1979 sb.append("0"); 1980 } 1981 sb.append(abs(y) as long); 1982 return sb.toString(); 1983 } 1984 1985 /** 1986 * TODO Until TZ support implemented, the time is calculated in UTC+0 and TZ string is hardcoded 1987 */ 1988 private timeZoneString(): String { 1989 let sb = new StringBuilder(); 1990 sb.append("GMT"); 1991 let offset = -this.TZOffset; 1992 let hours = offset / 60; 1993 if(hours < 0) { 1994 sb.append("-"); 1995 } else { 1996 sb.append("+") 1997 } 1998 if (abs(hours) < 10) { 1999 sb.append("0"); 2000 } 2001 sb.append(abs(hours)); 2002 let minutes = abs(offset % 60); 2003 if (minutes < 10) { 2004 sb.append("0"); 2005 } 2006 sb.append(minutes); 2007 sb.append(" ("); 2008 sb.append(Date.getTimezoneName()); 2009 sb.append(")"); 2010 2011 return sb.toString(); 2012 } 2013 /** 2014 * Returns a string representing the specified `Date` object interpreted in the local timezone. 2015 * 2016 * @see ECMA-262, 21.4.4.41 2017 * 2018 * @returns A string representing the given date. 2019 * 2020 * @example 2021 * ``` 2022 * let d = new Date(1979.0, 9.0, 27.0, 13.0, 12.8, 57.0, 444.1); 2023 * console.println(d.toString()); // Sat Oct 27 1979 13:12:57 GMT 2024 * ``` 2025 */ 2026 public override toString(): string { 2027 let res: String = "Invalid date"; 2028 try { 2029 res = this.toDateString() + " " + this.toTimeString(); 2030 } 2031 catch (e) {} 2032 return res; 2033 } 2034 2035 /** 2036 * Returns a string representing the specified `Date` object interpreted in UTC. 2037 * 2038 * @see ECMA-262, 21.4.4.41 2039 * 2040 * @returns A string representing the given date. 2041 * 2042 * @example 2043 * ``` 2044 * let d = new Date(1979.0, 9.0, 27.0, 13.0, 12.8, 57.0, 444.1); 2045 * console.println(d.toUTCString()); // Sat Oct 27 1979 13:12:57 GMT 2046 * ``` 2047 */ 2048 public toUTCString(): string { 2049 if (!this.isDateValid()) { 2050 throw new Error("Invalid Date"); 2051 } 2052 this.ms -= this.TZOffset * 60 * msPerSecond; 2053 let s: String = this.toDateString() + " " + this.toTimeString(); 2054 this.ms += this.TZOffset * 60 * msPerSecond; 2055 return s; 2056 } 2057} 2058