| | 422 | } |
|---|
| | 423 | |
|---|
| | 424 | |
|---|
| | 425 | /** |
|---|
| | 426 | * Crates a d_time time from a string. |
|---|
| | 427 | * |
|---|
| | 428 | * Params: |
|---|
| | 429 | * timeString = A time astring. |
|---|
| | 430 | * format = An optional format string, defaults to ISO 8601. |
|---|
| | 431 | * |
|---|
| | 432 | * Returns: A d_time time. |
|---|
| | 433 | */ |
|---|
| | 434 | public d_time toTime(char[] timeString) { |
|---|
| | 435 | d_datetime datetime; |
|---|
| | 436 | char[][] fields; |
|---|
| | 437 | FieldType[] ftypes; |
|---|
| | 438 | FieldType dtype; |
|---|
| | 439 | if (!parseDateTime(timeString, fields, ftypes)) { |
|---|
| | 440 | throw new ParseDateException(timeString ~ " can not be parsed as time"); |
|---|
| | 441 | } |
|---|
| | 442 | if (!decodeDateTime(fields, ftypes, dtype, datetime, false)) { |
|---|
| | 443 | throw new ParseDateException(timeString ~ " can not be parsed as time"); |
|---|
| | 444 | } |
|---|
| | 445 | switch (dtype) { |
|---|
| | 446 | case FieldType.TIME: |
|---|
| | 447 | break; |
|---|
| | 448 | case FieldType.EPOCH: |
|---|
| | 449 | assert(0); |
|---|
| | 450 | default: |
|---|
| | 451 | throw new ParseDateException(timeString ~ " can not be parsed as time"); |
|---|
| | 452 | } |
|---|
| | 453 | return toTime(datetime.hour, datetime.minute, datetime.second, datetime.millisecond); |
|---|
| | 454 | } |
|---|
| | 455 | unittest { |
|---|
| | 456 | // Also tests toTime(int, int, int) and toString(), splitTime() |
|---|
| | 457 | d_time t = toTime("12:01:02"); |
|---|
| | 458 | assert(toString(t) == "12:01:02"); |
|---|
| | 459 | assert(t == toTime(12, 1, 2)); |
|---|
| | 460 | // TODO: Allow for compact ISO times. |
|---|
| | 461 | // assert(t == toTime("120102")); |
|---|
| | 462 | assert(t == toTime("12:01:02.000")); |
|---|
| | 463 | assert(t == toTime("00:01:02 PM")); |
|---|
| | 464 | int h, m, s, ms; |
|---|
| | 465 | splitTime(t, h, m, s, ms); |
|---|
| | 466 | assert(h == 12); |
|---|
| | 467 | assert(m == 1); |
|---|
| | 468 | assert(s == 2); |
|---|
| | 469 | assert(ms == 0); |
|---|
| | 470 | } |
|---|
| | 471 | |
|---|
| | 472 | |
|---|
| | 473 | /** |
|---|
| | 474 | * Compose a d_time time from a hour, minute, second and millisecond part. |
|---|
| | 475 | * |
|---|
| | 476 | * Params: |
|---|
| | 477 | * hour = An hour. |
|---|
| | 478 | * minute = A minute. |
|---|
| | 479 | * second = A second. |
|---|
| | 480 | * millisecond = An optional millisecond, defaults to 0. |
|---|
| | 481 | * |
|---|
| | 482 | * Returns: Time as d_time. |
|---|
| | 483 | */ |
|---|
| | 484 | public d_time toTime(int hour, int minute, int second, int millisecond = 0) { |
|---|
| | 485 | d_time time; |
|---|
| | 486 | time = cast(d_time)(MSEC_PER_HOUR * hour + |
|---|
| | 487 | MSEC_PER_MIN * minute + |
|---|
| | 488 | MSEC_PER_SEC * second + |
|---|
| | 489 | millisecond); |
|---|
| | 490 | return normTime(time); |
|---|
| | 491 | } |
|---|
| | 492 | |
|---|
| | 493 | |
|---|
| | 494 | /** |
|---|
| | 495 | * Creates a time from a timestamp. |
|---|
| | 496 | * |
|---|
| | 497 | * Params: |
|---|
| | 498 | * timestamp = A d_timestamp date/time. |
|---|
| | 499 | * |
|---|
| | 500 | * Return: A d_time time. |
|---|
| | 501 | */ |
|---|
| | 502 | public d_time toTime(d_timestamp timestamp) { |
|---|
| | 503 | double d = cast(double)timestamp % 1.0; |
|---|
| | 504 | if (d < 0.0) { |
|---|
| | 505 | d += 1.0; |
|---|
| | 506 | } |
|---|
| | 507 | return cast(d_time)(d * MSEC_PER_DAY); |
|---|
| | 508 | } |
|---|
| | 509 | |
|---|
| | 510 | |
|---|
| | 511 | /** |
|---|
| | 512 | * Crates a d_timestamp date/time from a string. |
|---|
| | 513 | * |
|---|
| | 514 | * Params: |
|---|
| | 515 | * tsString = A date and time time string. |
|---|
| | 516 | * format = An optional format string, defaults to ISO 8601. |
|---|
| | 517 | * |
|---|
| | 518 | * Returns: A d_timestamp date/time. |
|---|
| | 519 | */ |
|---|
| | 520 | public d_timestamp toTimeStamp(char[] tsString) { |
|---|
| | 521 | d_datetime datetime; |
|---|
| | 522 | char[][] fields; |
|---|
| | 523 | FieldType[] ftypes; |
|---|
| | 524 | FieldType dtype; |
|---|
| | 525 | if (!parseDateTime(tsString, fields, ftypes)) { |
|---|
| | 526 | throw new ParseDateException(tsString ~ " can not be parsed as timestamp"); |
|---|
| | 527 | } |
|---|
| | 528 | if (!decodeDateTime(fields, ftypes, dtype, datetime, false)) { |
|---|
| | 529 | throw new ParseDateException(tsString ~ " can not be parsed as timestamp"); |
|---|
| | 530 | } |
|---|
| | 531 | switch (dtype) { |
|---|
| | 532 | case FieldType.DATE: |
|---|
| | 533 | break; |
|---|
| | 534 | case FieldType.EPOCH: |
|---|
| | 535 | assert(0); |
|---|
| | 536 | default: |
|---|
| | 537 | throw new ParseDateException(tsString ~ " can not be parsed as timestamp"); |
|---|
| | 538 | } |
|---|
| | 539 | d_date date = toDate(datetime.year, datetime.month, datetime.day); |
|---|
| | 540 | d_time time = toTime(datetime.hour, datetime.minute, datetime.second, datetime.millisecond); |
|---|
| | 541 | return toTimeStamp(date, time); |
|---|
| | 542 | } |
|---|
| | 543 | unittest { |
|---|
| | 544 | // Also tests toTimeStamp(int, int...), toTimeStamp(date, time), |
|---|
| | 545 | // toTimeStamp(int), toString(), and splitTimeStamp() |
|---|
| | 546 | d_timestamp ts = toTimeStamp("2006-03-19 11:42:00"); |
|---|
| | 547 | assert(ts == toTimeStamp(toDate("2006-03-19"), toTime("11:42:00"))); |
|---|
| | 548 | assert(toString(toTimeStamp(0)) == "1970-01-01 00:00:00"); |
|---|
| | 549 | d_date d = toDate(ts); |
|---|
| | 550 | d_time t = toTime(ts); |
|---|
| | 551 | assert(d == toDate(2006,3,19)); |
|---|
| | 552 | assert(t == toTime(11, 42, 0)); |
|---|
| | 553 | } |
|---|
| | 554 | |
|---|
| | 555 | |
|---|
| | 556 | /** |
|---|
| | 557 | * Convert a d_date date to a d_timestamp date/time. |
|---|
| | 558 | * |
|---|
| | 559 | * Params: |
|---|
| | 560 | * date = A d_date date. |
|---|
| | 561 | * |
|---|
| | 562 | * Returns: A d_timestamp date/time. |
|---|
| | 563 | */ |
|---|
| | 564 | public d_timestamp toTimeStamp(d_date date) { |
|---|
| | 565 | return cast(d_timestamp)date; |
|---|
| | 566 | } |
|---|
| | 567 | |
|---|
| | 568 | |
|---|
| | 569 | /** |
|---|
| | 570 | * Convert a d_time time to a d_timestamp date/time. |
|---|
| | 571 | * |
|---|
| | 572 | * Datepart will be today. |
|---|
| | 573 | * |
|---|
| | 574 | * Params: |
|---|
| | 575 | * time = A d_time time. |
|---|
| | 576 | * |
|---|
| | 577 | * Returns: A d_timestamp date/time. |
|---|
| | 578 | */ |
|---|
| | 579 | public d_timestamp toTimeStamp(d_time time) { |
|---|
| | 580 | return cast(d_timestamp)date() + cast(d_timestamp)(cast(double)time / |
|---|
| | 581 | MSEC_PER_DAY); |
|---|
| | 582 | } |
|---|
| | 583 | |
|---|
| | 584 | |
|---|
| | 585 | /** |
|---|
| | 586 | * Convert a d_date date and a d_time time to a d_timestamp date/time. |
|---|
| | 587 | * |
|---|
| | 588 | * Params: |
|---|
| | 589 | * date = A d_date date. |
|---|
| | 590 | * time = A d_time time. |
|---|
| | 591 | * |
|---|
| | 592 | * Returns: A d_timestamp date/time. |
|---|
| | 593 | */ |
|---|
| | 594 | public d_timestamp toTimeStamp(d_date date, d_time time) { |
|---|
| | 595 | return cast(d_timestamp)date + cast(d_timestamp)(cast(double)time / |
|---|
| | 596 | MSEC_PER_DAY); |
|---|
| | 597 | } |
|---|
| | 598 | |
|---|
| | 599 | |
|---|
| | 600 | /** |
|---|
| | 601 | * Compose a d_timestamp from a year, a month, and a day components. |
|---|
| | 602 | * |
|---|
| | 603 | * Values less than 1 indicates days from the end of the month, 0 is the last |
|---|
| | 604 | * day of the month, and -1 is the second to last, etc. |
|---|
| | 605 | * |
|---|
| | 606 | * Days that does not fit into a month will spill into the next month. Day 35 of |
|---|
| | 607 | * january will for example result in the 4th of february. |
|---|
| | 608 | * |
|---|
| | 609 | * Params: |
|---|
| | 610 | * year = A year. |
|---|
| | 611 | * month = A month of year. |
|---|
| | 612 | * day = A day of month. |
|---|
| | 613 | * hour = An hour. |
|---|
| | 614 | * minute = A minute. |
|---|
| | 615 | * second = A second. |
|---|
| | 616 | * millisecond = An optional millisecond, defaults to 0. |
|---|
| | 617 | * |
|---|
| | 618 | * Returns: Date/time as a d_timestamp. |
|---|
| | 619 | */ |
|---|
| | 620 | public d_timestamp toTimeStamp(int year, int month, int day, int hour, |
|---|
| | 621 | int minute, int second, int millisecond = 0) { |
|---|
| | 622 | return toTimeStamp(toDate(year, month, day), toTime(hour, minute, second, |
|---|
| | 623 | millisecond)); |
|---|
| | 624 | } |
|---|
| | 625 | |
|---|
| | 626 | |
|---|
| | 627 | /** |
|---|
| | 628 | * Compose a d_timestamp from a year, month, day, hour, minute, second, and |
|---|
| | 629 | * millisecond part. |
|---|
| | 630 | * |
|---|
| | 631 | * Values less than 1 indicates days from the end of the month, 0 is the last |
|---|
| | 632 | * day of the month, and -1 is the second to last, etc. |
|---|
| | 633 | * |
|---|
| | 634 | * Days that does not fit into a month will spill into the next month. Day 35 of |
|---|
| | 635 | * january will for example result in the 4th of february. |
|---|
| | 636 | * |
|---|
| | 637 | * Params: |
|---|
| | 638 | * year = A year. |
|---|
| | 639 | * month = A month of year. |
|---|
| | 640 | * day = A day of month. |
|---|
| | 641 | * |
|---|
| | 642 | * Returns: Date as a d_timestamp. |
|---|
| | 643 | */ |
|---|
| | 644 | public d_timestamp toDateTimeStamp(int year, int month, int day) { |
|---|
| | 645 | return toTimeStamp(toDate(year, month, day)); |
|---|
| | 646 | } |
|---|
| | 647 | |
|---|
| | 648 | |
|---|
| | 649 | /** |
|---|
| | 650 | * Compose a d_timestamp time from a hour, minute, second and millisecond part. |
|---|
| | 651 | * |
|---|
| | 652 | * Params: |
|---|
| | 653 | * hour = An hour. |
|---|
| | 654 | * minute = A minute. |
|---|
| | 655 | * second = A second. |
|---|
| | 656 | * millisecond = An optional millisecond, defaults to 0. |
|---|
| | 657 | * |
|---|
| | 658 | * Returns: Time as d_timestamp. |
|---|
| | 659 | */ |
|---|
| | 660 | public d_timestamp toTimeTimeStamp(int hour, int minute, int second, |
|---|
| | 661 | int millisecond) { |
|---|
| | 662 | return toTimeStamp(toTime(hour, minute, second, millisecond)); |
|---|
| | 663 | } |
|---|
| | 664 | |
|---|
| | 665 | |
|---|
| | 666 | /** |
|---|
| | 667 | * Creates a date/time from an *nix epoch. |
|---|
| | 668 | * |
|---|
| | 669 | * Params: |
|---|
| | 670 | * epoch = An *nix epoch. |
|---|
| | 671 | * |
|---|
| | 672 | * Return: A d_timestamp date/time. |
|---|
| | 673 | */ |
|---|
| | 674 | public d_timestamp toTimeStamp(int epoch) { |
|---|
| | 675 | double timestamp; |
|---|
| | 676 | timestamp = cast(double)epoch / SEC_PER_DAY; |
|---|
| | 677 | timestamp -= DATE_UNIX_EPOCH_OFFSET; |
|---|
| | 678 | return cast(d_timestamp)timestamp; |
|---|
| | 679 | } |
|---|
| | 680 | |
|---|
| | 681 | |
|---|
| | 682 | /** |
|---|
| | 683 | * Creates an d_duration duration from a string. |
|---|
| | 684 | * |
|---|
| | 685 | * Params: |
|---|
| | 686 | * durationString = A date string. |
|---|
| | 687 | * |
|---|
| | 688 | * Returns: An d_duration duration. |
|---|
| | 689 | */ |
|---|
| | 690 | public d_duration toDuration(char[] durationString) { |
|---|
| | 691 | d_datetime datetime; |
|---|
| | 692 | char[][] fields; |
|---|
| | 693 | FieldType[] ftypes; |
|---|
| | 694 | if (!parseDateTime(durationString, fields, ftypes)) { |
|---|
| | 695 | throw new ParseDateException(durationString ~ " can not be parsed as duration"); |
|---|
| | 696 | } |
|---|
| | 697 | if (!decodeDuration(fields, ftypes, datetime)) { |
|---|
| | 698 | throw new ParseDateException(durationString ~ " can not be parsed as duration"); |
|---|
| | 699 | } |
|---|
| | 700 | return toDuration(datetime.year, datetime.month, datetime.day, |
|---|
| | 701 | datetime.hour, datetime.minute, datetime.second, datetime.millisecond); |
|---|
| | 702 | } |
|---|
| | 703 | unittest { |
|---|
| | 704 | d_duration d = toDateDuration(1, 2, 3); |
|---|
| | 705 | assert(d == toDuration("1 year, 2 months and 3 days")); |
|---|
| | 706 | } |
|---|
| | 707 | |
|---|
| | 708 | |
|---|
| | 709 | /** |
|---|
| | 710 | * Creates an d_duration duration from years, months, days, hours, minutes, |
|---|
| | 711 | * seconds and milliseconds parts. |
|---|
| | 712 | * |
|---|
| | 713 | * Params: |
|---|
| | 714 | * years = Number of years. |
|---|
| | 715 | * months = Number of months. |
|---|
| | 716 | * days = Number of days. |
|---|
| | 717 | * hours = Numbr of hours. |
|---|
| | 718 | * minutes = Number of minutes. |
|---|
| | 719 | * seconds = Number of seconds. |
|---|
| | 720 | * milliseconds = Optional number of milliseconds, defaults to 0. |
|---|
| | 721 | * |
|---|
| | 722 | * Returns: An d_duration duration. |
|---|
| | 723 | */ |
|---|
| | 724 | public d_duration toDuration(int years, int months, int days, int hours, |
|---|
| | 725 | int minutes, int seconds, int milliseconds = 0) { |
|---|
| | 726 | d_duration duration; |
|---|
| | 727 | duration.daysAndTime = cast(double)days + |
|---|
| | 728 | (1.0 / HOUR_PER_DAY) * hours + |
|---|
| | 729 | (1.0 / MIN_PER_DAY) * minutes + |
|---|
| | 730 | (1.0 / SEC_PER_DAY) * seconds + |
|---|
| | 731 | (1.0 / MSEC_PER_DAY) * milliseconds; |
|---|
| | 732 | duration.months = years * 12 + months; |
|---|
| | 733 | return duration; |
|---|
| | 734 | } |
|---|
| | 735 | |
|---|
| | 736 | |
|---|
| | 737 | /** |
|---|
| | 738 | * Creates an d_duration duration from years, months, and days parts. |
|---|
| | 739 | * |
|---|
| | 740 | * Params: |
|---|
| | 741 | * years = Number of years. |
|---|
| | 742 | * months = Number of months. |
|---|
| | 743 | * days = Number of days. |
|---|
| | 744 | * |
|---|
| | 745 | * Returns: An d_duration duration. |
|---|
| | 746 | */ |
|---|
| | 747 | public d_duration toDateDuration(int years, int months, int days) { |
|---|
| | 748 | return toDuration(years, months, days, 0, 0, 0); |
|---|
| | 749 | } |
|---|
| | 750 | |
|---|
| | 751 | |
|---|
| | 752 | /** |
|---|
| | 753 | * Creates an d_duration duration from hours, minutes, seconds and milliseconds |
|---|
| | 754 | * parts. |
|---|
| | 755 | * |
|---|
| | 756 | * Params: |
|---|
| | 757 | * hours = Numbr of hours. |
|---|
| | 758 | * minutes = Number of minutes. |
|---|
| | 759 | * seconds = Number of seconds. |
|---|
| | 760 | * milliseconds = Optional number of milliseconds, defaults to 0. |
|---|
| | 761 | * |
|---|
| | 762 | * Returns: An d_duration duration. |
|---|
| | 763 | */ |
|---|
| | 764 | public d_duration toTimeDuration(int hours, int minutes, int seconds, int milliseconds = 0) { |
|---|
| | 765 | return toDuration(0, 0, 0, hours, minutes, seconds, milliseconds); |
|---|
| | 766 | } |
|---|
| | 767 | |
|---|
| | 768 | |
|---|
| | 769 | /** |
|---|
| | 770 | * Return the difference between two d_date dates as a d_duration duration. |
|---|
| | 771 | * |
|---|
| | 772 | * The difference can be extracted as an exact measure in days (default), and |
|---|
| | 773 | * optionally in relative measure by months and years. |
|---|
| | 774 | * |
|---|
| | 775 | * Params: |
|---|
| | 776 | * fromDate = A base d_date date. |
|---|
| | 777 | * toDate = A relative d_date date. |
|---|
| | 778 | * relative = If true duration is relative. |
|---|
| | 779 | * |
|---|
| | 780 | * Returns: A d_duration duration. |
|---|
| | 781 | */ |
|---|
| | 782 | public d_duration age(d_date fromDate, d_date toDate, bool relative = false) { |
|---|
| | 783 | d_duration duration; |
|---|
| | 784 | |
|---|
| | 785 | if (!relative) { |
|---|
| | 786 | duration.daysAndTime = cast(double)(toDate - fromDate); |
|---|
| | 787 | } else { |
|---|
| | 788 | int fromYear, fromMonth, fromDay; |
|---|
| | 789 | int toYear, toMonth, toDay; |
|---|
| | 790 | splitDate(fromDate, fromYear, fromMonth, fromDay); |
|---|
| | 791 | splitDate(toDate, toYear, toMonth, toDay); |
|---|
| | 792 | duration.daysAndTime = cast(double)(toDay - fromDay); |
|---|
| | 793 | duration.months = (toYear * 12 + toMonth) - (fromYear * 12 + fromMonth); |
|---|
| | 794 | } |
|---|
| | 795 | return duration; |
|---|
| | 796 | } |
|---|
| | 797 | |
|---|
| | 798 | |
|---|
| | 799 | /** |
|---|
| | 800 | * Return the difference between two d_time times as a d_duration duration. |
|---|
| | 801 | * |
|---|
| | 802 | * Params: |
|---|
| | 803 | * fromTime = A base d_time time. |
|---|
| | 804 | * toTime = A relative d_time time. |
|---|
| | 805 | * |
|---|
| | 806 | * Returns: A d_duration duration. |
|---|
| | 807 | */ |
|---|
| | 808 | public d_duration age(d_time fromTime, d_time toTime) { |
|---|
| | 809 | d_duration duration; |
|---|
| | 810 | duration.daysAndTime = cast(double)(toTime - fromTime); |
|---|
| | 811 | return duration; |
|---|
| | 812 | } |
|---|
| | 813 | |
|---|
| | 814 | |
|---|
| | 815 | /** |
|---|
| | 816 | * Return the difference between two d_timestamp date/times as a d_duration |
|---|
| | 817 | * duration. |
|---|
| | 818 | * |
|---|
| | 819 | * The difference can be extracted as an exact measure in days (default), and |
|---|
| | 820 | * optionally in relative measure by months and years. |
|---|
| | 821 | * |
|---|
| | 822 | * Params: |
|---|
| | 823 | * fromTimeStamp = A base d_timestamp date/time. |
|---|
| | 824 | * toTimeStamp = A relative d_timestamp date/time. |
|---|
| | 825 | * relative = If true duration is relative. |
|---|
| | 826 | * |
|---|
| | 827 | * Returns: A d_duration duration. |
|---|
| | 828 | */ |
|---|
| | 829 | public d_duration age(d_timestamp fromTimeStamp, d_timestamp toTimeStamp, |
|---|
| | 830 | bool relative = false) { |
|---|
| | 831 | d_duration duration; |
|---|
| | 832 | |
|---|
| | 833 | duration = age(toDate(fromTimeStamp), toDate(toTimeStamp), relative); |
|---|
| | 834 | duration.daysAndTime += cast(double)(toTime(toTimeStamp) - |
|---|
| | 835 | toTime(fromTimeStamp)); |
|---|
| | 836 | return duration; |
|---|
| | 884 | } |
|---|
| | 885 | |
|---|
| | 886 | |
|---|
| | 887 | /** |
|---|
| | 888 | * Split a d_time into hour, minute, second, and millisecond parts. |
|---|
| | 889 | * |
|---|
| | 890 | * Params: |
|---|
| | 891 | * time = A d_time time. |
|---|
| | 892 | * hour = (OUT) The hour. |
|---|
| | 893 | * minute = (OUT) The minute. |
|---|
| | 894 | * second = (OUT) The second. |
|---|
| | 895 | * millisecond = (OUT) The millisecond. |
|---|
| | 896 | */ |
|---|
| | 897 | public void splitTime(d_time time, out int hour, out int minute, out int second, |
|---|
| | 898 | out int millisecond) { |
|---|
| | 899 | time = normTime(time); |
|---|
| | 900 | hour = cast(int)time / MSEC_PER_HOUR; |
|---|
| | 901 | minute = cast(int)(time / MSEC_PER_MIN) % 60; |
|---|
| | 902 | second = cast(int)(time / MSEC_PER_SEC) % 60; |
|---|
| | 903 | millisecond = cast(int)time % 1000; |
|---|
| | 904 | } |
|---|
| | 905 | |
|---|
| | 906 | |
|---|
| | 907 | /** |
|---|
| | 908 | * Split a d_timestamp time into year, month, day, hour, minute, second, and |
|---|
| | 909 | * millisecond parts. |
|---|
| | 910 | * |
|---|
| | 911 | * Params: |
|---|
| | 912 | * timestamp = A d_timestamp date/time. |
|---|
| | 913 | * year = (OUT) The year. |
|---|
| | 914 | * month = (OUT) The month of year. |
|---|
| | 915 | * day = (OUT) The day of month. |
|---|
| | 916 | * hour = (OUT) The hour. |
|---|
| | 917 | * minute = (OUT) The minute. |
|---|
| | 918 | * second = (OUT) The second. |
|---|
| | 919 | * millisecond = (OUT) The millisecond. |
|---|
| | 920 | */ |
|---|
| | 921 | public void splitTimeStamp(d_timestamp timestamp, out int year, |
|---|
| | 922 | out int month, out int day, out int hour, out int minute, out int second, |
|---|
| | 923 | out int millisecond) { |
|---|
| | 924 | splitDate(toDate(timestamp), year, month, day); |
|---|
| | 925 | splitTime(toTime(timestamp), hour, minute, second, millisecond); |
|---|
| | 926 | } |
|---|
| | 927 | |
|---|
| | 928 | |
|---|
| | 929 | /** |
|---|
| | 930 | * Split a d_timestamp into year, month, and day components. |
|---|
| | 931 | * |
|---|
| | 932 | * Params: |
|---|
| | 933 | * timestamp = A d_timestamp date/time. |
|---|
| | 934 | * year = (OUT) The year. |
|---|
| | 935 | * month = (OUT) The month of year. |
|---|
| | 936 | * day = (OUT) The day of month. |
|---|
| | 937 | */ |
|---|
| | 938 | public void splitDateTimeStamp(d_timestamp timestamp, out int year, |
|---|
| | 939 | out int month, out int day) { |
|---|
| | 940 | splitDate(toDate(timestamp), year, month, day); |
|---|
| | 941 | } |
|---|
| | 942 | |
|---|
| | 943 | |
|---|
| | 944 | /** |
|---|
| | 945 | * Split a d_timestamp time into hour, minute, second, and millisecond parts. |
|---|
| | 946 | * |
|---|
| | 947 | * Params: |
|---|
| | 948 | * timestamp = A d_timestamp date/time. |
|---|
| | 949 | * hour = (OUT) The hour. |
|---|
| | 950 | * minute = (OUT) The minute. |
|---|
| | 951 | * second = (OUT) The second. |
|---|
| | 952 | * millisecond = (OUT) The millisecond. |
|---|
| | 953 | */ |
|---|
| | 954 | public void splitTimeTimeStamp(d_timestamp timestamp, out int hour, |
|---|
| | 955 | out int minute, out int second, out int millisecond) { |
|---|
| | 956 | splitTime(toTime(timestamp), hour, minute, second, millisecond); |
|---|
| | 957 | } |
|---|
| | 958 | |
|---|
| | 959 | |
|---|
| | 960 | /** |
|---|
| | 961 | * Splits an d_duration duration into years, months, days, hours, minutes, |
|---|
| | 962 | * seconds and milliseconds parts. |
|---|
| | 963 | * |
|---|
| | 964 | * Params: |
|---|
| | 965 | * years = (OUT) Number of years. |
|---|
| | 966 | * months = (OUT) Number of months. |
|---|
| | 967 | * days = (OUT) Number of days. |
|---|
| | 968 | * hours = (OUT) Numbr of hours. |
|---|
| | 969 | * minutes = (OUT) Number of minutes. |
|---|
| | 970 | * seconds = (OUT) Number of seconds. |
|---|
| | 971 | * milliseconds = (OUT) Number of milliseconds. |
|---|
| | 972 | */ |
|---|
| | 973 | public void splitDuration(d_duration duration, out int years, out int months, |
|---|
| | 974 | out int days, out int hours, out int minutes, out int seconds, out int milliseconds) { |
|---|
| | 975 | years = duration.months / 12; |
|---|
| | 976 | months = duration.months % 12; |
|---|
| | 977 | days = cast(int)duration.daysAndTime; |
|---|
| | 978 | float timePart = duration.daysAndTime - days; |
|---|
| | 979 | hours = cast(int)((timePart * HOUR_PER_DAY) % 24); |
|---|
| | 980 | minutes = cast(int)((timePart * MIN_PER_DAY) % 60); |
|---|
| | 981 | seconds = cast(int)((timePart * SEC_PER_DAY) % 60); |
|---|
| | 982 | milliseconds = cast(int)((timePart * MSEC_PER_DAY) % 1000); |
|---|
| | 983 | } |
|---|
| | 984 | |
|---|
| | 985 | |
|---|
| | 986 | /** |
|---|
| | 987 | * Splits an d_duration duration into years, months, and days parts. |
|---|
| | 988 | * |
|---|
| | 989 | * Params: |
|---|
| | 990 | * years = (OUT) Number of years. |
|---|
| | 991 | * months = (OUT) Number of months. |
|---|
| | 992 | * days = (OUT) Number of days. |
|---|
| | 993 | */ |
|---|
| | 994 | public void splitDateDuration(d_duration duration, out int years, |
|---|
| | 995 | out int months, out int days) { |
|---|
| | 996 | years = duration.months / 12; |
|---|
| | 997 | months = duration.months % 12; |
|---|
| | 998 | days = cast(int)duration.daysAndTime; |
|---|
| | 999 | // float timePart = duration.daysAndTime - days; |
|---|
| | 1000 | } |
|---|
| | 1001 | |
|---|
| | 1002 | |
|---|
| | 1003 | /** |
|---|
| | 1004 | * Splits an d_duration duration into hours, minutes, seconds and milliseconds |
|---|
| | 1005 | * parts. |
|---|
| | 1006 | * |
|---|
| | 1007 | * The days of the duration will be converted to hours, any months and/or years |
|---|
| | 1008 | * will be ignored as their length in hours can not be determined. |
|---|
| | 1009 | * |
|---|
| | 1010 | * Params: |
|---|
| | 1011 | * hours = (OUT) Numbr of hours. |
|---|
| | 1012 | * minutes = (OUT) Number of minutes. |
|---|
| | 1013 | * seconds = (OUT) Number of seconds. |
|---|
| | 1014 | * milliseconds = (OUT) Number of milliseconds. |
|---|
| | 1015 | * |
|---|
| | 1016 | */ |
|---|
| | 1017 | public void splitTimeDuration(d_duration duration, out int hours, |
|---|
| | 1018 | out int minutes, out int seconds, out int milliseconds) { |
|---|
| | 1019 | double timePart = duration.daysAndTime; |
|---|
| | 1020 | hours = cast(int)(timePart * HOUR_PER_DAY); |
|---|
| | 1021 | minutes = cast(int)((timePart * MIN_PER_DAY) % 60); |
|---|
| | 1022 | seconds = cast(int)((timePart * SEC_PER_DAY) % 60); |
|---|
| | 1023 | milliseconds = cast(int)((timePart * MSEC_PER_DAY) % 1000); |
|---|
| 519 | | * Incremet a d_date date's date part datePart by a count. |
|---|
| 520 | | * |
|---|
| 521 | | * Params: |
|---|
| 522 | | * date = A d_date date. |
|---|
| 523 | | * datePart = A DatePart dat part, in range MILLENIA..DAY. |
|---|
| 524 | | * count = A count of dateparts to increment. |
|---|
| 525 | | * |
|---|
| 526 | | * Returns: A d_date date. |
|---|
| 527 | | */ |
|---|
| 528 | | public d_date increment(d_date date, DatePart datePart, int count) { |
|---|
| 529 | | switch (datePart) { |
|---|
| 530 | | case DatePart.MILLENIA: |
|---|
| 531 | | return addYearsToDate(date, count * 1000); |
|---|
| 532 | | case DatePart.DECADE: |
|---|
| 533 | | return addYearsToDate(date, count * 10); |
|---|
| 534 | | case DatePart.YEAR: |
|---|
| 535 | | return addYearsToDate(date, count); |
|---|
| 536 | | case DatePart.QUARTER: |
|---|
| 537 | | return addMonthsToDate(date, count * 3); |
|---|
| 538 | | case DatePart.MONTH: |
|---|
| 539 | | return addMonthsToDate(date, count); |
|---|
| 540 | | case DatePart.WEEK: |
|---|
| 541 | | return date + count * 7; |
|---|
| 542 | | case DatePart.DAY: |
|---|
| 543 | | return date + count; |
|---|
| 544 | | default: |
|---|
| 545 | | throw new InvalidDatePartException(std.string.toString(cast(int)datePart) ~ |
|---|
| 546 | | " is an invalid date part"); |
|---|
| 547 | | } |
|---|
| 548 | | } |
|---|
| 549 | | |
|---|
| 550 | | |
|---|
| 551 | | /** |
|---|
| 552 | | * Increment d_date date with a d_duration duration. |
|---|
| 553 | | * |
|---|
| 554 | | * Params: |
|---|
| 555 | | * date = A d_date date. |
|---|
| 556 | | * duration = A d_duration duration. |
|---|
| 557 | | * |
|---|
| 558 | | * Returns: A d_date date. |
|---|
| 559 | | */ |
|---|
| 560 | | public d_date increment(d_date date, d_duration duration) { |
|---|
| 561 | | return addMonthsToDate(date, duration.months) + cast(int)duration.daysAndTime; |
|---|
| 562 | | } |
|---|
| 563 | | |
|---|
| 564 | | |
|---|
| 565 | | /** |
|---|
| 566 | | * Trunc a d_date date to a given date part. |
|---|
| 567 | | * |
|---|
| 568 | | * Params: |
|---|
| 569 | | * date = A d_date date. |
|---|
| 570 | | * datePart = A DatePart, in the range MILLENIA..WEEK. |
|---|
| 571 | | * |
|---|
| 572 | | * Returns: A d_date date. |
|---|
| 573 | | */ |
|---|
| 574 | | public d_date truncate(d_date date, DatePart datePart) { |
|---|
| 575 | | int year, month, day; |
|---|
| 576 | | splitDate(date, year, month, day); |
|---|
| 577 | | switch (datePart) { |
|---|
| 578 | | case DatePart.MILLENIA: |
|---|
| 579 | | year = (year / 1000) * 1000; |
|---|
| 580 | | month = 1; |
|---|
| 581 | | day = 1; |
|---|
| 582 | | break; |
|---|
| 583 | | case DatePart.DECADE: |
|---|
| 584 | | year = (year / 10) * 10; |
|---|
| 585 | | month = 1; |
|---|
| 586 | | day = 1; |
|---|
| 587 | | break; |
|---|
| 588 | | case DatePart.YEAR: |
|---|
| 589 | | month = 1; |
|---|
| 590 | | day = 1; |
|---|
| 591 | | break; |
|---|
| 592 | | case DatePart.QUARTER: |
|---|
| 593 | | month = ((month - 1) / 3) * 3 + 1; |
|---|
| 594 | | case DatePart.MONTH: |
|---|
| 595 | | day = 1; |
|---|
| 596 | | break; |
|---|
| 597 | | case DatePart.WEEK: |
|---|
| 598 | | return date - weekDayOfDate(date); |
|---|
| 599 | | default: |
|---|
| 600 | | throw new InvalidDatePartException(std.string.toString(cast(int)datePart) ~ |
|---|
| 601 | | " is an invalid date part"); |
|---|
| 602 | | } |
|---|
| 603 | | return toDate(year, month, day); |
|---|
| 604 | | } |
|---|
| 605 | | unittest { |
|---|
| 606 | | d_date d = toDate(2026, 10, 28); |
|---|
| 607 | | assert(truncate(d, DatePart.MILLENIA) == toDate(2000, 1, 1)); |
|---|
| 608 | | assert(truncate(d, DatePart.DECADE) == toDate(2020, 1, 1)); |
|---|
| 609 | | assert(truncate(d, DatePart.YEAR) == toDate(2026, 1, 1)); |
|---|
| 610 | | assert(truncate(d, DatePart.QUARTER) == toDate(2026, 10, 1)); |
|---|
| 611 | | assert(truncate(d, DatePart.MONTH) == toDate(2026, 10, 1)); |
|---|
| 612 | | assert(truncate(d, DatePart.WEEK) == toDate(2026, 10, 26)); |
|---|
| 613 | | } |
|---|
| 614 | | |
|---|
| 615 | | |
|---|
| 616 | | /** |
|---|
| 617 | | * Get current system local time. |
|---|
| 618 | | * |
|---|
| 619 | | * Returns: Current system local time as a d_time time. |
|---|
| 620 | | */ |
|---|
| 621 | | public d_time time() { |
|---|
| 622 | | tm* _tm = localtime(null); |
|---|
| 623 | | d_time time = toTime(_tm.tm_hour, _tm.tm_min, _tm.tm_sec, 0); |
|---|
| 624 | | //free(tm); |
|---|
| 625 | | return time; |
|---|
| 626 | | } |
|---|
| 627 | | |
|---|
| 628 | | |
|---|
| 629 | | /** |
|---|
| 630 | | * Get current system UDT time. |
|---|
| 631 | | * |
|---|
| 632 | | * Returns: Current system UDT time as a d_time time. |
|---|
| 633 | | */ |
|---|
| 634 | | public d_time udtTime() { |
|---|
| 635 | | tm* _tm = gmtime(null); |
|---|
| 636 | | d_time time = toTime(_tm.tm_hour, _tm.tm_min, _tm.tm_sec, 0); |
|---|
| 637 | | //free(tm); |
|---|
| 638 | | return time; |
|---|
| 639 | | } |
|---|
| 640 | | |
|---|
| 641 | | |
|---|
| 642 | | /** |
|---|
| 643 | | * Create a string from a d_time time. |
|---|
| 644 | | * |
|---|
| 645 | | * Params: |
|---|
| 646 | | * time = A d_time time. |
|---|
| 647 | | * format = An optional format string, defaults to ISO 8601. |
|---|
| 648 | | * |
|---|
| 649 | | * Returns: The d_time time as a string. |
|---|
| 650 | | */ |
|---|
| 651 | | public char[] toString(d_time time, char[] format = ISO_FORMAT_TIME) { |
|---|
| 652 | | int hour, minute, second, millisecond; |
|---|
| 653 | | |
|---|
| 654 | | assert(format == ISO_FORMAT_TIME); |
|---|
| 655 | | |
|---|
| 656 | | splitTime(time, hour, minute, second, millisecond); |
|---|
| 657 | | return std.string.format("%02d:%02d:%02d", hour, minute, second); |
|---|
| 658 | | } |
|---|
| 659 | | |
|---|
| 660 | | |
|---|
| 661 | | /** |
|---|
| 662 | | * Crates a d_time time from a string. |
|---|
| 663 | | * |
|---|
| 664 | | * Params: |
|---|
| 665 | | * timeString = A time astring. |
|---|
| 666 | | * format = An optional format string, defaults to ISO 8601. |
|---|
| 667 | | * |
|---|
| 668 | | * Returns: A d_time time. |
|---|
| 669 | | */ |
|---|
| 670 | | public d_time toTime(char[] timeString) { |
|---|
| 671 | | d_datetime datetime; |
|---|
| 672 | | char[][] fields; |
|---|
| 673 | | FieldType[] ftypes; |
|---|
| 674 | | FieldType dtype; |
|---|
| 675 | | if (!parseDateTime(timeString, fields, ftypes)) { |
|---|
| 676 | | throw new ParseDateException(timeString ~ " can not be parsed as time"); |
|---|
| 677 | | } |
|---|
| 678 | | if (!decodeDateTime(fields, ftypes, dtype, datetime, false)) { |
|---|
| 679 | | throw new ParseDateException(timeString ~ " can not be parsed as time"); |
|---|
| 680 | | } |
|---|
| 681 | | switch (dtype) { |
|---|
| 682 | | case FieldType.TIME: |
|---|
| 683 | | break; |
|---|
| 684 | | case FieldType.EPOCH: |
|---|
| 685 | | assert(0); |
|---|
| 686 | | default: |
|---|
| 687 | | throw new ParseDateException(timeString ~ " can not be parsed as time"); |
|---|
| 688 | | } |
|---|
| 689 | | return toTime(datetime.hour, datetime.minute, datetime.second, datetime.millisecond); |
|---|
| 690 | | } |
|---|
| 691 | | unittest { |
|---|
| 692 | | // Also tests toTime(int, int, int) and toString(), splitTime() |
|---|
| 693 | | d_time t = toTime("12:01:02"); |
|---|
| 694 | | assert(toString(t) == "12:01:02"); |
|---|
| 695 | | assert(t == toTime(12, 1, 2)); |
|---|
| 696 | | // TODO: Allow for compact ISO times. |
|---|
| 697 | | // assert(t == toTime("120102")); |
|---|
| 698 | | assert(t == toTime("12:01:02.000")); |
|---|
| 699 | | assert(t == toTime("00:01:02 PM")); |
|---|
| 700 | | int h, m, s, ms; |
|---|
| 701 | | splitTime(t, h, m, s, ms); |
|---|
| 702 | | assert(h == 12); |
|---|
| 703 | | assert(m == 1); |
|---|
| 704 | | assert(s == 2); |
|---|
| 705 | | assert(ms == 0); |
|---|
| 706 | | } |
|---|
| 707 | | |
|---|
| 708 | | |
|---|
| 709 | | /** |
|---|
| 710 | | * Compose a d_time time from a hour, minute, second and millisecond part. |
|---|
| 711 | | * |
|---|
| 712 | | * Params: |
|---|
| 713 | | * hour = An hour. |
|---|
| 714 | | * minute = A minute. |
|---|
| 715 | | * second = A second. |
|---|
| 716 | | * millisecond = An optional millisecond, defaults to 0. |
|---|
| 717 | | * |
|---|
| 718 | | * Returns: Time as d_time. |
|---|
| 719 | | */ |
|---|
| 720 | | public d_time toTime(int hour, int minute, int second, int millisecond = 0) { |
|---|
| 721 | | d_time time; |
|---|
| 722 | | time = cast(d_time)(MSEC_PER_HOUR * hour + |
|---|
| 723 | | MSEC_PER_MIN * minute + |
|---|
| 724 | | MSEC_PER_SEC * second + |
|---|
| 725 | | millisecond); |
|---|
| 726 | | return normTime(time); |
|---|
| 727 | | } |
|---|
| 728 | | |
|---|
| 729 | | |
|---|
| 730 | | /** |
|---|
| 731 | | * Split a d_time time into hour, minute, second, and millisecond parts. |
|---|
| 732 | | * |
|---|
| 733 | | * Params: |
|---|
| 734 | | * time = A d_time time. |
|---|
| 735 | | * hour = (OUT) The hour. |
|---|
| 736 | | * minute = (OUT) The minute. |
|---|
| 737 | | * second = (OUT) The second. |
|---|
| 738 | | * millisecond = (OUT) The millisecond. |
|---|
| 739 | | */ |
|---|
| 740 | | public void splitTime(d_time time, out int hour, out int minute, out int second, |
|---|
| 741 | | out int millisecond) { |
|---|
| 742 | | time = normTime(time); |
|---|
| 743 | | hour = cast(int)time / MSEC_PER_HOUR; |
|---|
| 744 | | minute = cast(int)(time / MSEC_PER_MIN) % 60; |
|---|
| 745 | | second = cast(int)(time / MSEC_PER_SEC) % 60; |
|---|
| 746 | | millisecond = cast(int)time % 1000; |
|---|
| 747 | | } |
|---|
| 748 | | |
|---|
| 749 | | |
|---|
| 750 | | /** |
|---|
| 788 | | * Trunc a d_time time to a given date part. |
|---|
| 789 | | * |
|---|
| 790 | | * Params: |
|---|
| 791 | | * time = A d_time date. |
|---|
| 792 | | * datePart = A DatePart, in the range HOUR..SECOND. |
|---|
| 793 | | * |
|---|
| 794 | | * Returns: A d_time time. |
|---|
| 795 | | */ |
|---|
| 796 | | public d_time truncate(d_time time, DatePart datePart) { |
|---|
| 797 | | time = normTime(time); |
|---|
| 798 | | switch (datePart) { |
|---|
| 799 | | case DatePart.HOUR: |
|---|
| 800 | | return cast(d_time)(cast(int)(time / MSEC_PER_HOUR) * MSEC_PER_HOUR); |
|---|
| 801 | | case DatePart.MINUTE: |
|---|
| 802 | | return cast(d_time)(cast(int)(time / MSEC_PER_MIN) * MSEC_PER_MIN); |
|---|
| 803 | | case DatePart.SECOND: |
|---|
| 804 | | return cast(d_time)(cast(int)(time / MSEC_PER_SEC) * MSEC_PER_SEC); |
|---|
| 805 | | default: |
|---|
| 806 | | throw new InvalidDatePartException(std.string.toString(cast(int)datePart) ~ |
|---|
| 807 | | " is an invalid date part"); |
|---|
| 808 | | } |
|---|
| 809 | | } |
|---|
| 810 | | unittest { |
|---|
| 811 | | d_time t = toTime(12, 13, 14, 15); |
|---|
| 812 | | assert(truncate(t, DatePart.SECOND) == toTime("12:13:14")); |
|---|
| 813 | | assert(truncate(t, DatePart.MINUTE) == toTime("12:13:00")); |
|---|
| 814 | | assert(truncate(t, DatePart.HOUR) == toTime("12:00:00")); |
|---|
| 815 | | } |
|---|
| 816 | | |
|---|
| 817 | | |
|---|
| 818 | | /** |
|---|
| 819 | | * Incremet a d_time times's date part datePart by a count. |
|---|
| 820 | | * |
|---|
| 821 | | * Params: |
|---|
| 822 | | * time = A d_time time. |
|---|
| 823 | | * datePart = A DatePart date part, in range HOUR..MILLISECOND. |
|---|
| 824 | | * count = A count of dateparts to increment. |
|---|
| 825 | | * |
|---|
| 826 | | * Returns: A d_time time. |
|---|
| 827 | | */ |
|---|
| 828 | | public d_time increment(d_time time, DatePart datePart, int count) { |
|---|
| 829 | | switch (datePart) { |
|---|
| 830 | | case DatePart.HOUR: |
|---|
| 831 | | time += cast(d_time)(count * MSEC_PER_HOUR); |
|---|
| 832 | | break; |
|---|
| 833 | | case DatePart.MINUTE: |
|---|
| 834 | | time += cast(d_time)(count * MSEC_PER_MIN); |
|---|
| 835 | | break; |
|---|
| 836 | | case DatePart.SECOND: |
|---|
| 837 | | time += cast(d_time)(count * MSEC_PER_SEC); |
|---|
| 838 | | break; |
|---|
| 839 | | case DatePart.MILLISECOND: |
|---|
| 840 | | time += cast(d_time)count; |
|---|
| 841 | | break; |
|---|
| 842 | | default: |
|---|
| 843 | | throw new InvalidDatePartException(std.string.toString(cast(int)datePart) ~ |
|---|
| 844 | | " is an invalid date part"); |
|---|
| 845 | | } |
|---|
| 846 | | return normTime(time); |
|---|
| 847 | | } |
|---|
| 848 | | |
|---|
| 849 | | |
|---|
| 850 | | /** |
|---|
| 851 | | * Increment d_time time with a d_duration duration. |
|---|
| 852 | | * |
|---|
| 853 | | * Params: |
|---|
| 854 | | * time = A d_time time. |
|---|
| 855 | | * duration = A d_duration duration. |
|---|
| 856 | | * |
|---|
| 857 | | * Returns: A d_time time. |
|---|
| 858 | | */ |
|---|
| 859 | | public d_time increment(d_time time, d_duration duration) { |
|---|
| 860 | | time += cast(d_time)(duration.daysAndTime * MSEC_PER_DAY) % |
|---|
| 861 | | MSEC_PER_DAY; |
|---|
| 862 | | return normTime(time); |
|---|
| 863 | | } |
|---|
| 864 | | |
|---|
| 865 | | |
|---|
| 866 | | /** |
|---|
| 867 | | * Create a string from a d_timestamp date/time. |
|---|
| 868 | | * |
|---|
| 869 | | * Params: |
|---|
| 870 | | * timestamp = A timestamnp_t date/time. |
|---|
| 871 | | * format = An optional format string, defaults to ISO 8601. |
|---|
| 872 | | * |
|---|
| 873 | | * Returns: The d_timestamp time as a string. |
|---|
| 874 | | */ |
|---|
| 875 | | public char[] toString(d_timestamp timestamp, |
|---|
| 876 | | char[] format = ISO_FORMAT_TIMESTAMP) { |
|---|
| 877 | | assert(format == ISO_FORMAT_TIMESTAMP); |
|---|
| 878 | | |
|---|
| 879 | | return toString(dateOfTimeStamp(timestamp), format[0..8]) ~ " " ~ |
|---|
| 880 | | toString(timeOfTimeStamp(timestamp), format[9..$]); |
|---|
| 881 | | } |
|---|
| 882 | | |
|---|
| 883 | | |
|---|
| 884 | | /** |
|---|
| 885 | | * Crates a d_timestamp date/time from a string. |
|---|
| 886 | | * |
|---|
| 887 | | * Params: |
|---|
| 888 | | * tsString = A date and time time string. |
|---|
| 889 | | * format = An optional format string, defaults to ISO 8601. |
|---|
| 890 | | * |
|---|
| 891 | | * Returns: A d_timestamp date/time. |
|---|
| 892 | | */ |
|---|
| 893 | | public d_timestamp toTimeStamp(char[] tsString) { |
|---|
| 894 | | d_datetime datetime; |
|---|
| 895 | | char[][] fields; |
|---|
| 896 | | FieldType[] ftypes; |
|---|
| 897 | | FieldType dtype; |
|---|
| 898 | | if (!parseDateTime(tsString, fields, ftypes)) { |
|---|
| 899 | | throw new ParseDateException(tsString ~ " can not be parsed as timestamp"); |
|---|
| 900 | | } |
|---|
| 901 | | if (!decodeDateTime(fields, ftypes, dtype, datetime, false)) { |
|---|
| 902 | | throw new ParseDateException(tsString ~ " can not be parsed as timestamp"); |
|---|
| 903 | | } |
|---|
| 904 | | switch (dtype) { |
|---|
| 905 | | case FieldType.DATE: |
|---|
| 906 | | break; |
|---|
| 907 | | case FieldType.EPOCH: |
|---|
| 908 | | assert(0); |
|---|
| 909 | | default: |
|---|
| 910 | | throw new ParseDateException(tsString ~ " can not be parsed as timestamp"); |
|---|
| 911 | | } |
|---|
| 912 | | d_date date = toDate(datetime.year, datetime.month, datetime.day); |
|---|
| 913 | | d_time time = toTime(datetime.hour, datetime.minute, datetime.second, datetime.millisecond); |
|---|
| 914 | | return toTimeStamp(date, time); |
|---|
| 915 | | } |
|---|
| 916 | | unittest { |
|---|
| 917 | | // Also tests toTimeStamp(int, int...), toTimeStamp(date, time), |
|---|
| 918 | | // toTimeStamp(int), toString(), and splitTimeStamp() |
|---|
| 919 | | d_timestamp ts = toTimeStamp("2006-03-19 11:42:00"); |
|---|
| 920 | | assert(ts == toTimeStamp(toDate("2006-03-19"), toTime("11:42:00"))); |
|---|
| 921 | | assert(toString(toTimeStamp(0)) == "1970-01-01 00:00:00"); |
|---|
| 922 | | d_date d; |
|---|
| 923 | | d_time t; |
|---|
| 924 | | splitTimeStamp(ts, d, t); |
|---|
| 925 | | assert(d == toDate(2006,3,19)); |
|---|
| 926 | | assert(t == toTime(11, 42, 0)); |
|---|
| 927 | | } |
|---|
| 928 | | |
|---|
| 929 | | |
|---|
| 930 | | /** |
|---|
| 931 | | * Convert a d_date date to a d_timestamp date/time. |
|---|
| 932 | | * |
|---|
| 933 | | * Params: |
|---|
| 934 | | * date = A d_date date. |
|---|
| 935 | | * |
|---|
| 936 | | * Returns: A d_timestamp date/time. |
|---|
| 937 | | */ |
|---|
| 938 | | public d_timestamp toTimeStamp(d_date date) { |
|---|
| 939 | | return cast(d_timestamp)date; |
|---|
| 940 | | } |
|---|
| 941 | | |
|---|
| 942 | | |
|---|
| 943 | | /** |
|---|
| 944 | | * Convert a d_time time to a d_timestamp date/time. |
|---|
| 945 | | * |
|---|
| 946 | | * Params: |
|---|
| 947 | | * time = A d_time time. |
|---|
| 948 | | * |
|---|
| 949 | | * Returns: A d_timestamp date/time. |
|---|
| 950 | | */ |
|---|
| 951 | | public d_timestamp toTimeStamp(d_time time) { |
|---|
| 952 | | return cast(d_timestamp)date() + cast(d_timestamp)(cast(double)time / |
|---|
| 953 | | MSEC_PER_DAY); |
|---|
| 954 | | } |
|---|
| 955 | | |
|---|
| 956 | | |
|---|
| 957 | | /** |
|---|
| 958 | | * Convert a d_date date and a d_time time to a d_timestamp date/time. |
|---|
| 959 | | * |
|---|
| 960 | | * Params: |
|---|
| 961 | | * date = A d_date date. |
|---|
| 962 | | * time = A d_time time. |
|---|
| 963 | | * |
|---|
| 964 | | * Returns: A d_timestamp date/time. |
|---|
| 965 | | */ |
|---|
| 966 | | public d_timestamp toTimeStamp(d_date date, d_time time) { |
|---|
| 967 | | return cast(d_timestamp)date + cast(d_timestamp)(cast(double)time / |
|---|
| 968 | | MSEC_PER_DAY); |
|---|
| 969 | | } |
|---|
| 970 | | |
|---|
| 971 | | |
|---|
| 972 | | /** |
|---|
| 973 | | * Creates a date/time from an *nix epoch. |
|---|
| 974 | | * |
|---|
| 975 | | * Params: |
|---|
| 976 | | * epoch = An *nix epoch. |
|---|
| 977 | | * |
|---|
| 978 | | * Return: A d_timestamp date/time. |
|---|
| 979 | | */ |
|---|
| 980 | | public d_timestamp toTimeStamp(int epoch) { |
|---|
| 981 | | double timestamp; |
|---|
| 982 | | timestamp = cast(double)epoch / SEC_PER_DAY; |
|---|
| 983 | | timestamp -= DATE_UNIX_EPOCH_OFFSET; |
|---|
| 984 | | return cast(d_timestamp)timestamp; |
|---|
| 985 | | } |
|---|
| 986 | | |
|---|
| 987 | | |
|---|
| 988 | | /** |
|---|
| 989 | | * Split a d_timestamp date/time into d_date date, and d_time time components. |
|---|
| 990 | | * |
|---|
| 991 | | * Params: |
|---|
| 992 | | * timestamp = A timetamp_t date/time. |
|---|
| 993 | | * date = (OUT) A d_date date. |
|---|
| 994 | | * time = (OUT) A d_time time. |
|---|
| 995 | | */ |
|---|
| 996 | | public void splitTimeStamp(d_timestamp timestamp, out d_date date, |
|---|
| 997 | | out d_time time) { |
|---|
| 998 | | date = dateOfTimeStamp(timestamp); |
|---|
| 999 | | time = timeOfTimeStamp(timestamp); |
|---|
| 1000 | | } |
|---|
| 1001 | | |
|---|
| 1002 | | |
|---|
| 1003 | | |
|---|
| 1004 | | /** |
|---|
| 1042 | | } |
|---|
| 1043 | | |
|---|
| 1044 | | |
|---|
| 1045 | | /** |
|---|
| 1046 | | * Trunc a d_timestamp date to a given date part. |
|---|
| 1047 | | * |
|---|
| 1048 | | * Params: |
|---|
| 1049 | | * timestamp = A d_timestamp date/time. |
|---|
| 1050 | | * datePart = A DatePart, in the range MILLENIA..DAY, HOUR..SECOND. |
|---|
| 1051 | | * |
|---|
| 1052 | | * Returns: A d_timestamp date/time. |
|---|
| 1053 | | */ |
|---|
| 1054 | | public d_timestamp truncate(d_timestamp timestamp, DatePart datePart) { |
|---|
| 1055 | | if (datePart == DatePart.DAY) { |
|---|
| 1056 | | return cast(d_timestamp)(cast(int)timestamp); |
|---|
| 1057 | | } else { |
|---|
| 1058 | | if (datePart < DatePart.HOUR) { |
|---|
| 1059 | | return toTimeStamp(truncate(dateOfTimeStamp(timestamp), datePart), 0); |
|---|
| 1060 | | } else { |
|---|
| 1061 | | return toTimeStamp(dateOfTimeStamp(timestamp), |
|---|
| 1062 | | truncate(timeOfTimeStamp(timestamp), datePart)); |
|---|
| 1063 | | } |
|---|
| 1064 | | } |
|---|
| 1065 | | } |
|---|
| 1066 | | unittest { |
|---|
| 1067 | | d_timestamp ts = toTimeStamp("2006-03-19 12:26:42"); |
|---|
| 1068 | | assert(truncate(ts, DatePart.MINUTE) == toTimeStamp("2006-03-19 12:26:00")); |
|---|
| 1069 | | assert(truncate(ts, DatePart.HOUR) == toTimeStamp("2006-03-19 12:00:00")); |
|---|
| 1070 | | assert(truncate(ts, DatePart.DAY) == toTimeStamp("2006-03-19 00:00:00")); |
|---|
| 1071 | | assert(truncate(ts, DatePart.WEEK) == toTimeStamp("2006-03-13 00:00:00")); |
|---|
| 1072 | | assert(truncate(ts, DatePart.MONTH) == toTimeStamp("2006-03-01 00:00:00")); |
|---|
| 1073 | | assert(truncate(ts, DatePart.QUARTER) == toTimeStamp("2006-01-01 00:00:00")); |
|---|
| 1074 | | assert(truncate(ts, DatePart.YEAR) == toTimeStamp("2006-01-01 00:00:00")); |
|---|
| 1075 | | assert(truncate(ts, DatePart.DECADE) == toTimeStamp("2000-01-01 00:00:00")); |
|---|
| 1076 | | assert(truncate(ts, DatePart.MILLENIA) == toTimeStamp("2000-01-01 00:00:00")); |
|---|
| 1077 | | } |
|---|
| 1078 | | |
|---|
| 1079 | | |
|---|
| 1080 | | /** |
|---|
| 1081 | | * Incremet a d_timestamp date/times's date part datePart by a count. |
|---|
| 1082 | | * |
|---|
| 1083 | | * Params: |
|---|
| 1084 | | * timestamp = A d_timestamp date/time. |
|---|
| 1085 | | * datePart = A DatePart date part, in range MILLENIA..MILLISECOND. |
|---|
| 1086 | | * count = A count of dateparts to increment. |
|---|
| 1087 | | * |
|---|
| 1088 | | * Returns: A d_time time. |
|---|
| 1089 | | */ |
|---|
| 1090 | | public d_timestamp increment(d_timestamp timestamp, DatePart datePart, int count) { |
|---|
| 1091 | | if (datePart < DatePart.HOUR) { |
|---|
| 1092 | | return toTimeStamp(increment(dateOfTimeStamp(timestamp), datePart, count), |
|---|
| 1093 | | timeOfTimeStamp(timestamp)); |
|---|
| 1094 | | } else { |
|---|
| 1095 | | switch (datePart) { |
|---|
| 1096 | | case DatePart.HOUR: |
|---|
| 1097 | | timestamp += cast(d_timestamp)(count * (1.0 / HOUR_PER_DAY)); |
|---|
| 1098 | | break; |
|---|
| 1099 | | case DatePart.MINUTE: |
|---|
| 1100 | | timestamp += cast(d_timestamp)(count * (1.0 / MIN_PER_DAY)); |
|---|
| 1101 | | break; |
|---|
| 1102 | | case DatePart.SECOND: |
|---|
| 1103 | | timestamp += cast(d_timestamp)(count * (1.0 / SEC_PER_DAY)); |
|---|
| 1104 | | break; |
|---|
| 1105 | | case DatePart.MILLISECOND: |
|---|
| 1106 | | timestamp += cast(d_timestamp)(count * (1.0 / MSEC_PER_DAY)); |
|---|
| 1107 | | break; |
|---|
| 1108 | | default: |
|---|
| 1109 | | throw new InvalidDatePartException(std.string.toString(cast(int)datePart) ~ |
|---|
| 1110 | | " is an invalid date part"); |
|---|
| 1111 | | } |
|---|
| 1112 | | return timestamp; |
|---|
| 1113 | | } |
|---|
| 1114 | | } |
|---|
| 1115 | | |
|---|
| 1116 | | |
|---|
| 1117 | | /** |
|---|
| 1118 | | * Increment d_timestamp date/time with a d_duration duration. |
|---|
| 1119 | | * |
|---|
| 1120 | | * Params: |
|---|
| 1121 | | * timestamp = A d_time time. |
|---|
| 1122 | | * duration = A d_duration duration. |
|---|
| 1123 | | * |
|---|
| 1124 | | * Returns: A d_timestamp date/time. |
|---|
| 1125 | | */ |
|---|
| 1126 | | public d_timestamp increment(d_timestamp timestamp, d_duration duration) { |
|---|
| 1127 | | return increment(timestamp, DatePart.MONTH, duration.months) + |
|---|
| 1128 | | cast(d_timestamp)duration.daysAndTime; |
|---|
| 1129 | | } |
|---|
| 1130 | | |
|---|
| 1131 | | |
|---|
| 1132 | | /** |
|---|
| 1133 | | * Get the d_date date part of a d_timestamp date/time. |
|---|
| 1134 | | * |
|---|
| 1135 | | * Params: |
|---|
| 1136 | | * timestamp = A d_timestamp date/time. |
|---|
| 1137 | | * |
|---|
| 1138 | | * Returns: A d_date date. |
|---|
| 1139 | | */ |
|---|
| 1140 | | public d_date dateOfTimeStamp(d_timestamp timestamp) { |
|---|
| 1141 | | return cast(d_date)timestamp; |
|---|
| 1142 | | } |
|---|
| 1143 | | |
|---|
| 1144 | | |
|---|
| 1145 | | /** |
|---|
| 1146 | | * Replace the date part of a d_timestamp date/time. |
|---|
| 1147 | | * |
|---|
| 1148 | | * Params: |
|---|
| 1149 | | * timestamp = (INOUT) A d_timestamp date/time. |
|---|
| 1150 | | * date = A d_date date. |
|---|
| 1151 | | */ |
|---|
| 1152 | | public void setDateOfTimeStamp(inout d_timestamp timestamp, d_date date) { |
|---|
| 1153 | | timestamp = timestamp - cast(d_timestamp)(cast(long)timestamp) + |
|---|
| 1154 | | cast(d_timestamp)date; |
|---|
| 1155 | | } |
|---|
| 1156 | | |
|---|
| 1157 | | |
|---|
| 1158 | | /** |
|---|
| 1159 | | * Get the d_time date part of a d_timestamp date/time. |
|---|
| 1160 | | * |
|---|
| 1161 | | * Params: |
|---|
| 1162 | | * timestamp = A d_timestamp date/time. |
|---|
| 1163 | | * |
|---|
| 1164 | | * Returns: A d_time time. |
|---|
| 1165 | | */ |
|---|
| 1166 | | public d_time timeOfTimeStamp(d_timestamp timestamp) { |
|---|
| 1167 | | return cast(d_time)((cast(double)timestamp * MSEC_PER_DAY) % MSEC_PER_DAY); |
|---|
| 1168 | | } |
|---|
| 1169 | | |
|---|
| 1170 | | |
|---|
| 1171 | | /** |
|---|
| 1172 | | * Replace the time part of a d_timestamp date/time. |
|---|
| 1173 | | * |
|---|
| 1174 | | * Params: |
|---|
| 1175 | | * timestamp = (INOUT) A d_timestamp date/time. |
|---|
| 1176 | | * time = A d_time time. |
|---|
| 1177 | | */ |
|---|
| 1178 | | public void setTimeOfTimeStamp(inout d_timestamp timestamp, d_time time) { |
|---|
| 1179 | | timestamp = cast(d_timestamp)(cast(long)timestamp) + |
|---|
| 1180 | | cast(d_timestamp)(cast(double)time / MSEC_PER_DAY); |
|---|
| 1181 | | } |
|---|
| 1182 | | |
|---|
| 1183 | | |
|---|
| 1184 | | /** |
|---|
| 1185 | | * Create a string from a d_duration duration. |
|---|
| 1186 | | * |
|---|
| 1187 | | * Params: |
|---|
| 1188 | | * duration = An d_duration duration. |
|---|
| 1189 | | * |
|---|
| 1190 | | * Returns: The d_duration duration as a string. |
|---|
| 1191 | | */ |
|---|
| 1192 | | public char[] toString(d_duration duration) { |
|---|
| 1193 | | assert(0); |
|---|
| 1194 | | } |
|---|
| 1195 | | |
|---|
| 1196 | | |
|---|
| 1197 | | /** |
|---|
| 1198 | | * Creates an d_duration duration from a string. |
|---|
| 1199 | | * |
|---|
| 1200 | | * Params: |
|---|
| 1201 | | * durationString = A date string. |
|---|
| 1202 | | * |
|---|
| 1203 | | * Returns: An d_duration duration. |
|---|
| 1204 | | */ |
|---|
| 1205 | | public d_duration toDuration(char[] durationString) { |
|---|
| 1206 | | d_datetime datetime; |
|---|
| 1207 | | char[][] fields; |
|---|
| 1208 | | FieldType[] ftypes; |
|---|
| 1209 | | if (!parseDateTime(durationString, fields, ftypes)) { |
|---|
| 1210 | | throw new ParseDateException(durationString ~ " can not be parsed as duration"); |
|---|
| 1211 | | } |
|---|
| 1212 | | if (!decodeDuration(fields, ftypes, datetime)) { |
|---|
| 1213 | | throw new ParseDateException(durationString ~ " can not be parsed as duration"); |
|---|
| 1214 | | } |
|---|
| 1215 | | return toDuration(datetime.year, datetime.month, datetime.day, |
|---|
| 1216 | | datetime.hour, datetime.minute, datetime.second, datetime.millisecond); |
|---|
| 1217 | | } |
|---|
| 1218 | | unittest { |
|---|
| 1219 | | d_duration d = toDateDuration(1, 2, 3); |
|---|
| 1220 | | assert(d == toDuration("1 year, 2 months and 3 days")); |
|---|
| 1221 | | } |
|---|
| 1222 | | |
|---|
| 1223 | | |
|---|
| 1224 | | /** |
|---|
| 1225 | | * Creates an d_duration duration from years, months, days, hours, minutes, |
|---|
| 1226 | | * seconds and milliseconds parts. |
|---|
| 1227 | | * |
|---|
| 1228 | | * Params: |
|---|
| 1229 | | * years = Number of years. |
|---|
| 1230 | | * months = Number of months. |
|---|
| 1231 | | * days = Number of days. |
|---|
| 1232 | | * hours = Numbr of hours. |
|---|
| 1233 | | * minutes = Number of minutes. |
|---|
| 1234 | | * seconds = Number of seconds. |
|---|
| 1235 | | * milliseconds = Optional number of milliseconds, defaults to 0. |
|---|
| 1236 | | * |
|---|
| 1237 | | * Returns: An d_duration duration. |
|---|
| 1238 | | */ |
|---|
| 1239 | | public d_duration toDuration(int years, int months, int days, int hours, |
|---|
| 1240 | | int minutes, int seconds, int milliseconds = 0) { |
|---|
| 1241 | | d_duration duration; |
|---|
| 1242 | | duration.daysAndTime = cast(double)days + |
|---|
| 1243 | | (1.0 / HOUR_PER_DAY) * hours + |
|---|
| 1244 | | (1.0 / MIN_PER_DAY) * minutes + |
|---|
| 1245 | | (1.0 / SEC_PER_DAY) * seconds + |
|---|
| 1246 | | (1.0 / MSEC_PER_DAY) * milliseconds; |
|---|
| 1247 | | duration.months = years * 12 + months; |
|---|
| 1248 | | return duration; |
|---|
| 1249 | | } |
|---|
| 1250 | | |
|---|
| 1251 | | |
|---|
| 1252 | | /** |
|---|
| 1253 | | * Creates an d_duration duration from years, months, and days parts. |
|---|
| 1254 | | * |
|---|
| 1255 | | * Params: |
|---|
| 1256 | | * years = Number of years. |
|---|
| 1257 | | * months = Number of months. |
|---|
| 1258 | | * days = Number of days. |
|---|
| 1259 | | * |
|---|
| 1260 | | * Returns: An d_duration duration. |
|---|
| 1261 | | */ |
|---|
| 1262 | | public d_duration toDateDuration(int years, int months, int days) { |
|---|
| 1263 | | return toDuration(years, months, days, 0, 0, 0); |
|---|
| 1264 | | } |
|---|
| 1265 | | |
|---|
| 1266 | | |
|---|
| 1267 | | /** |
|---|
| 1268 | | * Creates an d_duration duration from hours, minutes, seconds and milliseconds |
|---|
| 1269 | | * parts. |
|---|
| 1270 | | * |
|---|
| 1271 | | * Params: |
|---|
| 1272 | | * hours = Numbr of hours. |
|---|
| 1273 | | * minutes = Number of minutes. |
|---|
| 1274 | | * seconds = Number of seconds. |
|---|
| 1275 | | * milliseconds = Optional number of milliseconds, defaults to 0. |
|---|
| 1276 | | * |
|---|
| 1277 | | * Returns: An d_duration duration. |
|---|
| 1278 | | */ |
|---|
| 1279 | | public d_duration toTimeDuration(int hours, int minutes, int seconds, int milliseconds = 0) { |
|---|
| 1280 | | return toDuration(0, 0, 0, hours, minutes, seconds, milliseconds); |
|---|
| 1281 | | } |
|---|
| 1282 | | |
|---|
| 1283 | | |
|---|
| 1284 | | /** |
|---|
| 1285 | | * Splits an d_duration duration into years, months, days, hours, minutes, |
|---|
| 1286 | | * seconds and milliseconds parts. |
|---|
| 1287 | | * |
|---|
| 1288 | | * Params: |
|---|
| 1289 | | * years = (OUT) Number of years. |
|---|
| 1290 | | * months = (OUT) Number of months. |
|---|
| 1291 | | * days = (OUT) Number of days. |
|---|
| 1292 | | * hours = (OUT) Numbr of hours. |
|---|
| 1293 | | * minutes = (OUT) Number of minutes. |
|---|
| 1294 | | * seconds = (OUT) Number of seconds. |
|---|
| 1295 | | * milliseconds = (OUT) Number of milliseconds. |
|---|
| 1296 | | */ |
|---|
| 1297 | | public void splitDuration(d_duration duration, out int years, out int months, |
|---|
| 1298 | | out int days, out int hours, out int minutes, out int seconds, out int milliseconds) { |
|---|
| 1299 | | years = duration.months / 12; |
|---|
| 1300 | | months = duration.months % 12; |
|---|
| 1301 | | days = cast(int)duration.daysAndTime; |
|---|
| 1302 | | float timePart = duration.daysAndTime - days; |
|---|
| 1303 | | hours = cast(int)((timePart * HOUR_PER_DAY) % 24); |
|---|
| 1304 | | minutes = cast(int)((timePart * MIN_PER_DAY) % 60); |
|---|
| 1305 | | seconds = cast(int)((timePart * SEC_PER_DAY) % 60); |
|---|
| 1306 | | milliseconds = cast(int)((timePart * MSEC_PER_DAY) % 1000); |
|---|
| 1307 | | } |
|---|
| 1308 | | |
|---|
| 1309 | | |
|---|
| 1310 | | /** |
|---|
| 1311 | | * Splits an d_duration duration into years, months, and days parts. |
|---|
| 1312 | | * |
|---|
| 1313 | | * Params: |
|---|
| 1314 | | * years = (OUT) Number of years. |
|---|
| 1315 | | * months = (OUT) Number of months. |
|---|
| 1316 | | * days = (OUT) Number of days. |
|---|
| 1317 | | */ |
|---|
| 1318 | | public void splitDateDuration(d_duration duration, out int years, |
|---|
| 1319 | | out int months, out int days) { |
|---|
| 1320 | | years = duration.months / 12; |
|---|
| 1321 | | months = duration.months % 12; |
|---|
| 1322 | | days = cast(int)duration.daysAndTime; |
|---|
| 1323 | | // float timePart = duration.daysAndTime - days; |
|---|
| 1324 | | } |
|---|
| 1325 | | |
|---|
| 1326 | | |
|---|
| 1327 | | /** |
|---|
| 1328 | | * Splits an d_duration duration into hours, minutes, seconds and milliseconds |
|---|
| 1329 | | * parts. |
|---|
| 1330 | | * |
|---|
| 1331 | | * The days of the duration will be converted to hours, any months and/or years |
|---|
| 1332 | | * will be ignored as their length in hours can not be determined. |
|---|
| 1333 | | * |
|---|
| 1334 | | * Params: |
|---|
| 1335 | | * hours = (OUT) Numbr of hours. |
|---|
| 1336 | | * minutes = (OUT) Number of minutes. |
|---|
| 1337 | | * seconds = (OUT) Number of seconds. |
|---|
| 1338 | | * milliseconds = (OUT) Number of milliseconds. |
|---|
| 1339 | | * |
|---|
| 1340 | | */ |
|---|
| 1341 | | public void splitTimeDuration(d_duration duration, out int hours, |
|---|
| 1342 | | out int minutes, out int seconds, out int milliseconds) { |
|---|
| 1343 | | double timePart = duration.daysAndTime; |
|---|
| 1344 | | hours = cast(int)(timePart * HOUR_PER_DAY); |
|---|
| 1345 | | minutes = cast(int)((timePart * MIN_PER_DAY) % 60); |
|---|
| 1346 | | seconds = cast(int)((timePart * SEC_PER_DAY) % 60); |
|---|
| 1347 | | milliseconds = cast(int)((timePart * MSEC_PER_DAY) % 1000); |
|---|
| 1456 | | return duration; |
|---|
| | 1253 | } |
|---|
| | 1254 | |
|---|
| | 1255 | |
|---|
| | 1256 | /** |
|---|
| | 1257 | * Increment d_date date with a d_duration duration. |
|---|
| | 1258 | * |
|---|
| | 1259 | * Params: |
|---|
| | 1260 | * date = A d_date date. |
|---|
| | 1261 | * duration = A d_duration duration. |
|---|
| | 1262 | * |
|---|
| | 1263 | * Returns: A d_date date. |
|---|
| | 1264 | */ |
|---|
| | 1265 | public d_date increment(d_date date, d_duration duration) { |
|---|
| | 1266 | return addMonthsToDate(date, duration.months) + cast(int)duration.daysAndTime; |
|---|
| | 1267 | } |
|---|
| | 1268 | |
|---|
| | 1269 | |
|---|
| | 1270 | /** |
|---|
| | 1271 | * Incremet a d_time times's date part datePart by a count. |
|---|
| | 1272 | * |
|---|
| | 1273 | * Params: |
|---|
| | 1274 | * time = A d_time time. |
|---|
| | 1275 | * datePart = A DatePart date part, in range HOUR..MILLISECOND. |
|---|
| | 1276 | * count = A count of dateparts to increment. |
|---|
| | 1277 | * |
|---|
| | 1278 | * Returns: A d_time time. |
|---|
| | 1279 | */ |
|---|
| | 1280 | public d_time increment(d_time time, DatePart datePart, int count) { |
|---|
| | 1281 | switch (datePart) { |
|---|
| | 1282 | case DatePart.HOUR: |
|---|
| | 1283 | time += cast(d_time)(count * MSEC_PER_HOUR); |
|---|
| | 1284 | break; |
|---|
| | 1285 | case DatePart.MINUTE: |
|---|
| | 1286 | time += cast(d_time)(count * MSEC_PER_MIN); |
|---|
| | 1287 | break; |
|---|
| | 1288 | case DatePart.SECOND: |
|---|
| | 1289 | time += cast(d_time)(count * MSEC_PER_SEC); |
|---|
| | 1290 | break; |
|---|
| | 1291 | case DatePart.MILLISECOND: |
|---|
| | 1292 | time += cast(d_time)count; |
|---|
| | 1293 | break; |
|---|
| | 1294 | default: |
|---|
| | 1295 | throw new InvalidDatePartException(std.string.toString(cast(int)datePart) ~ |
|---|
| | 1296 | " is an invalid date part"); |
|---|
| | 1297 | } |
|---|
| | 1298 | return normTime(time); |
|---|
| | 1299 | } |
|---|
| | 1300 | |
|---|
| | 1301 | |
|---|
| | 1302 | /** |
|---|
| | 1303 | * Increment d_time time with a d_duration duration. |
|---|
| | 1304 | * |
|---|
| | 1305 | * Params: |
|---|
| | 1306 | * time = A d_time time. |
|---|
| | 1307 | * duration = A d_duration duration. |
|---|
| | 1308 | * |
|---|
| | 1309 | * Returns: A d_time time. |
|---|
| | 1310 | */ |
|---|
| | 1311 | public d_time increment(d_time time, d_duration duration) { |
|---|
| | 1312 | time += cast(d_time)(duration.daysAndTime * MSEC_PER_DAY) % |
|---|
| | 1313 | MSEC_PER_DAY; |
|---|
| | 1314 | return normTime(time); |
|---|
| | 1315 | } |
|---|
| | 1316 | |
|---|
| | 1317 | |
|---|
| | 1318 | /** |
|---|
| | 1319 | * Incremet a d_timestamp date/times's date part datePart by a count. |
|---|
| | 1320 | * |
|---|
| | 1321 | * Params: |
|---|
| | 1322 | * timestamp = A d_timestamp date/time. |
|---|
| | 1323 | * datePart = A DatePart date part, in range MILLENIA..MILLISECOND. |
|---|
| | 1324 | * count = A count of dateparts to increment. |
|---|
| | 1325 | * |
|---|
| | 1326 | * Returns: A d_time time. |
|---|
| | 1327 | */ |
|---|
| | 1328 | public d_timestamp increment(d_timestamp timestamp, DatePart datePart, int count) { |
|---|
| | 1329 | if (datePart < DatePart.HOUR) { |
|---|
| | 1330 | return toTimeStamp(increment(toDate(timestamp), datePart, count), |
|---|
| | 1331 | toTime(timestamp)); |
|---|
| | 1332 | } else { |
|---|
| | 1333 | switch (datePart) { |
|---|
| | 1334 | case DatePart.HOUR: |
|---|
| | 1335 | timestamp += cast(d_timestamp)(count * (1.0 / HOUR_PER_DAY)); |
|---|
| | 1336 | break; |
|---|
| | 1337 | case DatePart.MINUTE: |
|---|
| | 1338 | timestamp += cast(d_timestamp)(count * (1.0 / MIN_PER_DAY)); |
|---|
| | 1339 | break; |
|---|
| | 1340 | case DatePart.SECOND: |
|---|
| | 1341 | timestamp += cast(d_timestamp)(count * (1.0 / SEC_PER_DAY)); |
|---|
| | 1342 | break; |
|---|
| | 1343 | case DatePart.MILLISECOND: |
|---|
| | 1344 | timestamp += cast(d_timestamp)(count * (1.0 / MSEC_PER_DAY)); |
|---|
| | 1345 | break; |
|---|
| | 1346 | default: |
|---|
| | 1347 | throw new InvalidDatePartException(std.string.toString(cast(int)datePart) ~ |
|---|
| | 1348 | " is an invalid date part"); |
|---|
| | 1349 | } |
|---|
| | 1350 | return timestamp; |
|---|
| | 1351 | } |
|---|
| | 1352 | } |
|---|
| | 1353 | |
|---|
| | 1354 | |
|---|
| | 1355 | /** |
|---|
| | 1356 | * Increment d_timestamp date/time with a d_duration duration. |
|---|
| | 1357 | * |
|---|
| | 1358 | * Params: |
|---|
| | 1359 | * timestamp = A d_time time. |
|---|
| | 1360 | * duration = A d_duration duration. |
|---|
| | 1361 | * |
|---|
| | 1362 | * Returns: A d_timestamp date/time. |
|---|
| | 1363 | */ |
|---|
| | 1364 | public d_timestamp increment(d_timestamp timestamp, d_duration duration) { |
|---|
| | 1365 | return increment(timestamp, DatePart.MONTH, duration.months) + |
|---|
| | 1366 | cast(d_timestamp)duration.daysAndTime; |
|---|
| 1532 | | * Return the difference between two d_date dates as a d_duration duration. |
|---|
| 1533 | | * |
|---|
| 1534 | | * The difference can be extracted as an exact measure in days (default), and |
|---|
| 1535 | | * optionally in relative measure by months and years. |
|---|
| 1536 | | * |
|---|
| 1537 | | * Params: |
|---|
| 1538 | | * fromDate = A base d_date date. |
|---|
| 1539 | | * toDate = A relative d_date date. |
|---|
| 1540 | | * relative = If true duration is relative. |
|---|
| 1541 | | * |
|---|
| 1542 | | * Returns: A d_duration duration. |
|---|
| 1543 | | */ |
|---|
| 1544 | | public d_duration age(d_date fromDate, d_date toDate, bool relative = false) { |
|---|
| 1545 | | d_duration duration; |
|---|
| | 1442 | * Trunc a d_date date to a given date part. |
|---|
| | 1443 | * |
|---|
| | 1444 | * Params: |
|---|
| | 1445 | * date = A d_date date. |
|---|
| | 1446 | * datePart = A DatePart, in the range MILLENIA..WEEK. |
|---|
| | 1447 | * |
|---|
| | 1448 | * Returns: A d_date date. |
|---|
| | 1449 | */ |
|---|
| | 1450 | public d_date truncate(d_date date, DatePart datePart) { |
|---|
| | 1451 | int year, month, day; |
|---|
| | 1452 | splitDate(date, year, month, day); |
|---|
| | 1453 | switch (datePart) { |
|---|
| | 1454 | case DatePart.MILLENIA: |
|---|
| | 1455 | year = (year / 1000) * 1000; |
|---|
| | 1456 | month = 1; |
|---|
| | 1457 | day = 1; |
|---|
| | 1458 | break; |
|---|
| | 1459 | case DatePart.DECADE: |
|---|
| | 1460 | year = (year / 10) * 10; |
|---|
| | 1461 | month = 1; |
|---|
| | 1462 | day = 1; |
|---|
| | 1463 | break; |
|---|
| | 1464 | case DatePart.YEAR: |
|---|
| | 1465 | month = 1; |
|---|
| | 1466 | day = 1; |
|---|
| | 1467 | break; |
|---|
| | 1468 | case DatePart.QUARTER: |
|---|
| | 1469 | month = ((month - 1) / 3) * 3 + 1; |
|---|
| | 1470 | case DatePart.MONTH: |
|---|
| | 1471 | day = 1; |
|---|
| | 1472 | break; |
|---|
| | 1473 | case DatePart.WEEK: |
|---|
| | 1474 | return date - weekDayOfDate(date); |
|---|
| | 1475 | default: |
|---|
| | 1476 | throw new InvalidDatePartException(std.string.toString(cast(int)datePart) ~ |
|---|
| | 1477 | " is an invalid date part"); |
|---|
| | 1478 | } |
|---|
| | 1479 | return toDate(year, month, day); |
|---|
| | 1480 | } |
|---|
| | 1481 | unittest { |
|---|
| | 1482 | d_date d = toDate(2026, 10, 28); |
|---|
| | 1483 | assert(truncate(d, DatePart.MILLENIA) == toDate(2000, 1, 1)); |
|---|
| | 1484 | assert(truncate(d, DatePart.DECADE) == toDate(2020, 1, 1)); |
|---|
| | 1485 | assert(truncate(d, DatePart.YEAR) == toDate(2026, 1, 1)); |
|---|
| | 1486 | assert(truncate(d, DatePart.QUARTER) == toDate(2026, 10, 1)); |
|---|
| | 1487 | assert(truncate(d, DatePart.MONTH) == toDate(2026, 10, 1)); |
|---|
| | 1488 | assert(truncate(d, DatePart.WEEK) == toDate(2026, 10, 26)); |
|---|
| | 1489 | } |
|---|
| | 1490 | |
|---|
| | 1491 | |
|---|
| | 1492 | /** |
|---|
| | 1493 | * Trunc a d_time time to a given date part. |
|---|
| | 1494 | * |
|---|
| | 1495 | * Params: |
|---|
| | 1496 | * time = A d_time date. |
|---|
| | 1497 | * datePart = A DatePart, in the range HOUR..SECOND. |
|---|
| | 1498 | * |
|---|
| | 1499 | * Returns: A d_time time. |
|---|
| | 1500 | */ |
|---|
| | 1501 | public d_time truncate(d_time time, DatePart datePart) { |
|---|
| | 1502 | time = normTime(time); |
|---|
| | 1503 | switch (datePart) { |
|---|
| | 1504 | case DatePart.HOUR: |
|---|
| | 1505 | return cast(d_time)(cast(int)(time / MSEC_PER_HOUR) * MSEC_PER_HOUR); |
|---|
| | 1506 | case DatePart.MINUTE: |
|---|
| | 1507 | return cast(d_time)(cast(int)(time / MSEC_PER_MIN) * MSEC_PER_MIN); |
|---|
| | 1508 | case DatePart.SECOND: |
|---|
| | 1509 | return cast(d_time)(cast(int)(time / MSEC_PER_SEC) * MSEC_PER_SEC); |
|---|
| | 1510 | default: |
|---|
| | 1511 | throw new InvalidDatePartException(std.string.toString(cast(int)datePart) ~ |
|---|
| | 1512 | " is an invalid date part"); |
|---|
| | 1513 | } |
|---|
| | 1514 | } |
|---|
| | 1515 | unittest { |
|---|
| | 1516 | d_time t = toTime(12, 13, 14, 15); |
|---|
| | 1517 | assert(truncate(t, DatePart.SECOND) == toTime("12:13:14")); |
|---|
| | 1518 | assert(truncate(t, DatePart.MINUTE) == toTime("12:13:00")); |
|---|
| | 1519 | assert(truncate(t, DatePart.HOUR) == toTime("12:00:00")); |
|---|
| | 1520 | } |
|---|
| | 1521 | |
|---|
| | 1522 | |
|---|
| | 1523 | /** |
|---|
| | 1524 | * Trunc a d_timestamp date to a given date part. |
|---|
| | 1525 | * |
|---|
| | 1526 | * Params: |
|---|
| | 1527 | * timestamp = A d_timestamp date/time. |
|---|
| | 1528 | * datePart = A DatePart, in the range MILLENIA..DAY, HOUR..SECOND. |
|---|
| | 1529 | * |
|---|
| | 1530 | * Returns: A d_timestamp date/time. |
|---|
| | 1531 | */ |
|---|
| | 1532 | public d_timestamp truncate(d_timestamp timestamp, DatePart datePart) { |
|---|
| | 1533 | if (datePart == DatePart.DAY) { |
|---|
| | 1534 | return cast(d_timestamp)(cast(int)timestamp); |
|---|
| | 1535 | } else { |
|---|
| | 1536 | if (datePart < DatePart.HOUR) { |
|---|
| | 1537 | return toTimeStamp(truncate(toDate(timestamp), datePart), 0); |
|---|
| | 1538 | } else { |
|---|
| | 1539 | return toTimeStamp(toDate(timestamp), |
|---|
| | 1540 | truncate(toTime(timestamp), datePart)); |
|---|
| | 1541 | } |
|---|
| | 1542 | } |
|---|
| | 1543 | } |
|---|
| | 1544 | unittest { |
|---|
| | 1545 | d_timestamp ts = toTimeStamp("2006-03-19 12:26:42"); |
|---|
| | 1546 | assert(truncate(ts, DatePart.MINUTE) == toTimeStamp("2006-03-19 12:26:00")); |
|---|
| | 1547 | assert(truncate(ts, DatePart.HOUR) == toTimeStamp("2006-03-19 12:00:00")); |
|---|
| | 1548 | assert(truncate(ts, DatePart.DAY) == toTimeStamp("2006-03-19 00:00:00")); |
|---|
| | 1549 | assert(truncate(ts, DatePart.WEEK) == toTimeStamp("2006-03-13 00:00:00")); |
|---|
| | 1550 | assert(truncate(ts, DatePart.MONTH) == toTimeStamp("2006-03-01 00:00:00")); |
|---|
| | 1551 | assert(truncate(ts, DatePart.QUARTER) == toTimeStamp("2006-01-01 00:00:00")); |
|---|
| | 1552 | assert(truncate(ts, DatePart.YEAR) == toTimeStamp("2006-01-01 00:00:00")); |
|---|
| | 1553 | assert(truncate(ts, DatePart.DECADE) == toTimeStamp("2000-01-01 00:00:00")); |
|---|
| | 1554 | assert(truncate(ts, DatePart.MILLENIA) == toTimeStamp("2000-01-01 00:00:00")); |
|---|
| | 1555 | } |
|---|
| | 1556 | |
|---|
| | 1557 | |
|---|
| | 1558 | /** |
|---|
| | 1559 | * Trunc an d_duration duration to a given date part. |
|---|
| | 1560 | * |
|---|
| | 1561 | * When truncing to dateparts in the range MILLENIA..MONTH all days will be |
|---|
| | 1562 | * removed even if they theoretically could make up a larger date part. |
|---|
| | 1563 | * |
|---|
| | 1564 | * Params: |
|---|
| | 1565 | * duration = An d_duration duration. |
|---|
| | 1566 | * datePart = A DatePart, in the range MILLENIA..DAY, HOUR..SECOND. |
|---|
| | 1567 | * |
|---|
| | 1568 | * Returns: A d_timestamp date/time. |
|---|
| | 1569 | */ |
|---|
| | 1570 | public d_duration truncate(d_duration duration, DatePart datePart) { |
|---|
| | 1571 | if (datePart < DatePart.WEEK) { |
|---|
| | 1572 | duration.daysAndTime = 0.0; |
|---|
| | 1573 | } |
|---|
| | 1574 | switch (datePart) { |
|---|
| | 1575 | case DatePart.MILLENIA: |
|---|
| | 1576 | duration.months = (duration.months / (12 * 1000)) * (12 *1000); |
|---|
| | 1577 | break; |
|---|
| | 1578 | case DatePart.DECADE: |
|---|
| | 1579 | duration.months = (duration.months / (12 * 10)) * (12 *1); |
|---|
| | 1580 | break; |
|---|
| | 1581 | case DatePart.YEAR: |
|---|
| | 1582 | duration.months = (duration.months / 12) * 12; |
|---|
| | 1583 | break; |
|---|
| | 1584 | case DatePart.QUARTER: |
|---|
| | 1585 | duration.months = (duration.months / 3) * 3; |
|---|
| | 1586 | break; |
|---|
| | 1587 | case DatePart.MONTH: |
|---|
| | 1588 | duration.months = (duration.months / (12 * 1000)) * (12 *1000); |
|---|
| | 1589 | break; |
|---|
| | 1590 | case DatePart.WEEK: |
|---|
| | 1591 | duration.daysAndTime = cast(int)(duration.daysAndTime / 7) * |
|---|
| | 1592 | cast(double)7.0; |
|---|
| | 1593 | break; |
|---|
| | 1594 | case DatePart.DAY: |
|---|
| | 1595 | duration.daysAndTime = cast(double)(cast(int)duration.daysAndTime); |
|---|
| | 1596 | break; |
|---|
| | 1597 | case DatePart.HOUR: |
|---|
| | 1598 | duration.daysAndTime = cast(int)(cast(double)duration.daysAndTime * |
|---|
| | 1599 | HOUR_PER_DAY) / cast(double)HOUR_PER_DAY; |
|---|
| | 1600 | break; |
|---|
| | 1601 | case DatePart.MINUTE: |
|---|
| | 1602 | duration.daysAndTime = cast(int)(cast(double)duration.daysAndTime * |
|---|
| | 1603 | MIN_PER_DAY) / cast(double)MIN_PER_DAY; |
|---|
| | 1604 | break; |
|---|
| | 1605 | case DatePart.SECOND: |
|---|
| | 1606 | duration.daysAndTime = cast(int)(cast(double)duration.daysAndTime * |
|---|
| | 1607 | SEC_PER_DAY) / cast(double)SEC_PER_DAY; |
|---|
| | 1608 | break; |
|---|
| | 1609 | default: |
|---|
| | 1610 | throw new InvalidDatePartException(std.string.toString(cast(int)datePart) ~ |
|---|
| | 1611 | " is an invalid date part"); |
|---|
| | 1612 | } |
|---|
| | 1613 | return duration; |
|---|
| | 1614 | } |
|---|
| | 1615 | |
|---|
| | 1616 | |
|---|
| | 1617 | /** |
|---|
| | 1618 | * Create a string from a d_date date. |
|---|
| | 1619 | * |
|---|
| | 1620 | * Params: |
|---|
| | 1621 | * date = A d_date date. |
|---|
| | 1622 | * format = An optional format string, defaults to ISO 8601. |
|---|
| | 1623 | * |
|---|
| | 1624 | * Returns: The d_date date as a string. |
|---|
| | 1625 | */ |
|---|
| | 1626 | public char[] toString(d_date date, char[] format = ISO_FORMAT_DATE) { |
|---|
| | 1627 | assert(format == ISO_FORMAT_DATE); |
|---|
| | 1628 | int year, month, day; |
|---|
| | 1629 | splitDate(date, year, month, day); |
|---|
| | 1630 | return std.string.format("%04d-%02d-%02d", year, month, day); |
|---|
| | 1631 | } |
|---|
| | 1632 | |
|---|
| | 1633 | |
|---|
| | 1634 | /** |
|---|
| | 1635 | * Create a string from a d_time time. |
|---|
| | 1636 | * |
|---|
| | 1637 | * Params: |
|---|
| | 1638 | * time = A d_time time. |
|---|
| | 1639 | * format = An optional format string, defaults to ISO 8601. |
|---|
| | 1640 | * |
|---|
| | 1641 | * Returns: The d_time time as a string. |
|---|
| | 1642 | */ |
|---|
| | 1643 | public char[] toString(d_time time, char[] format = ISO_FORMAT_TIME) { |
|---|
| | 1644 | int hour, minute, second, millisecond; |
|---|
| | 1645 | |
|---|
| | 1646 | assert(format == ISO_FORMAT_TIME); |
|---|
| | 1647 | |
|---|
| | 1648 | splitTime(time, hour, minute, second, millisecond); |
|---|
| | 1649 | return std.string.format("%02d:%02d:%02d", hour, minute, second); |
|---|
| | 1650 | } |
|---|
| | 1651 | |
|---|
| | 1652 | |
|---|
| | 1653 | /** |
|---|
| | 1654 | * Create a string from a d_timestamp date/time. |
|---|
| | 1655 | * |
|---|
| | 1656 | * Params: |
|---|
| | 1657 | * timestamp = A timestamnp_t date/time. |
|---|
| | 1658 | * format = An optional format string, defaults to ISO 8601. |
|---|
| | 1659 | * |
|---|
| | 1660 | * Returns: The d_timestamp time as a string. |
|---|
| | 1661 | */ |
|---|
| | 1662 | public char[] toString(d_timestamp timestamp, |
|---|
| | 1663 | char[] format = ISO_FORMAT_TIMESTAMP) { |
|---|
| | 1664 | assert(format == ISO_FORMAT_TIMESTAMP); |
|---|