Changeset 50
- Timestamp:
- 03/27/06 14:38:52 (6 years ago)
- Files:
-
- branches/date.d (modified) (40 diffs)
- branches/dateparse.d (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/date.d
r49 r50 28 28 * Gregorian dates. 29 29 * 30 * Using the asumption that a year is 365.2425 days, correct dates can be 31 * calculated for well beyond 5 million years into the future. Dates before 32 * 1900 are to complex to warrant for a date handler. 30 * The filosophy of this module is that dates, times and durations are discrete 31 * values no more complex than integers and floats. 32 * 33 * Code for parsing dates, times and durations have been taken and rewritten, 34 * from the PostgreSQL C source code. As such they are very complete and 35 * competent. A huge thanks to the PostgreSQL hackers! 33 36 * 34 37 * Authors: Fredrik Olsson <peylow@treyst.se> 35 38 * Standards: Conforms to ISO 8601 39 * Bugs: Does not handle the special case of compact ISO 8601 times (HHMMSS). 40 * Date: 2006-03-27 41 * 36 42 */ 37 43 … … 202 208 */ 203 209 public int weeksInYear(int year) { 204 return datePart(toDate(year, 12, 31), DatePart.WEEK);210 return extract(toDate(year, 12, 31), DatePart.WEEK); 205 211 } 206 212 … … 254 260 * Returns: The d_date date as a string. 255 261 */ 256 public char[] dateToString(d_date date, char[] format = ISO_FORMAT_DATE) {262 public char[] toString(d_date date, char[] format = ISO_FORMAT_DATE) { 257 263 assert(format == ISO_FORMAT_DATE); 258 264 int year, month, day; … … 452 458 * Returns: The datepart of a date. 453 459 */ 454 public int datePart(d_date date, DatePart datePart) {460 public int extract(d_date date, DatePart datePart) { 455 461 if (datePart != DatePart.WEEK && datePart != DatePart.WEEKDAY) { 456 462 if (datePart == DatePart.YEARDAY) { … … 477 483 return day; 478 484 default: 479 throw new InvalidDatePartException( toString(cast(int)datePart) ~485 throw new InvalidDatePartException(std.string.toString(cast(int)datePart) ~ 480 486 " is an invalid date part"); 481 487 } … … 490 496 } 491 497 unittest { 492 // Also tests inc Date(DatePart, int) and incDate(duration)498 // Also tests increment(DatePart, int) and increment(duration) 493 499 // And toDuration(int, int, int) 494 500 d_date d = toDate("2006-03-10"); 495 assert( datePart(d, DatePart.YEARDAY) == 69);496 d = inc Date(d, DatePart.WEEK, 1); // 2006-03-17497 assert( datePart(d, DatePart.WEEKDAY) == 4);498 d = inc Date(d, DatePart.MONTH, 1); // 2006-04-17499 assert( datePart(d, DatePart.MONTH) == 4);500 d = inc Date(d, DatePart.YEAR, 2); // 2008-04-17501 assert( datePart(d, DatePart.DAY) == 17);502 d = inc Date(d, toDateDuration(-1, 1, -6)); // 2007-05-11503 assert( datePart(d, DatePart.DECADE) == 200);504 assert( datePart(d, DatePart.YEAR) == 2007);505 assert( datePart(d, DatePart.QUARTER) == 2);506 assert( datePart(d, DatePart.WEEK) == 19);507 d = inc Date(d, toDateDuration(-4100, 14, 200)); // 2092-01-07 BCE508 assert( datePart(d, DatePart.MILLENIA) == -2);501 assert(extract(d, DatePart.YEARDAY) == 69); 502 d = increment(d, DatePart.WEEK, 1); // 2006-03-17 503 assert(extract(d, DatePart.WEEKDAY) == 4); 504 d = increment(d, DatePart.MONTH, 1); // 2006-04-17 505 assert(extract(d, DatePart.MONTH) == 4); 506 d = increment(d, DatePart.YEAR, 2); // 2008-04-17 507 assert(extract(d, DatePart.DAY) == 17); 508 d = increment(d, toDateDuration(-1, 1, -6)); // 2007-05-11 509 assert(extract(d, DatePart.DECADE) == 200); 510 assert(extract(d, DatePart.YEAR) == 2007); 511 assert(extract(d, DatePart.QUARTER) == 2); 512 assert(extract(d, DatePart.WEEK) == 19); 513 d = increment(d, toDateDuration(-4100, 14, 200)); // 2092-01-07 BCE 514 assert(extract(d, DatePart.MILLENIA) == -2); 509 515 } 510 516 … … 520 526 * Returns: A d_date date. 521 527 */ 522 public d_date inc Date(d_date date, DatePart datePart, int count) {528 public d_date increment(d_date date, DatePart datePart, int count) { 523 529 switch (datePart) { 524 530 case DatePart.MILLENIA: … … 537 543 return date + count; 538 544 default: 539 throw new InvalidDatePartException( toString(cast(int)datePart) ~545 throw new InvalidDatePartException(std.string.toString(cast(int)datePart) ~ 540 546 " is an invalid date part"); 541 547 } … … 552 558 * Returns: A d_date date. 553 559 */ 554 public d_date inc Date(d_date date, d_duration duration) {560 public d_date increment(d_date date, d_duration duration) { 555 561 return addMonthsToDate(date, duration.months) + cast(int)duration.daysAndTime; 556 562 } … … 566 572 * Returns: A d_date date. 567 573 */ 568 public d_date trunc Date(d_date date, DatePart datePart) {574 public d_date truncate(d_date date, DatePart datePart) { 569 575 int year, month, day; 570 576 splitDate(date, year, month, day); … … 592 598 return date - weekDayOfDate(date); 593 599 default: 594 throw new InvalidDatePartException( toString(cast(int)datePart) ~600 throw new InvalidDatePartException(std.string.toString(cast(int)datePart) ~ 595 601 " is an invalid date part"); 596 602 } … … 599 605 unittest { 600 606 d_date d = toDate(2026, 10, 28); 601 assert(trunc Date(d, DatePart.MILLENIA) == toDate(2000, 1, 1));602 assert(trunc Date(d, DatePart.DECADE) == toDate(2020, 1, 1));603 assert(trunc Date(d, DatePart.YEAR) == toDate(2026, 1, 1));604 assert(trunc Date(d, DatePart.QUARTER) == toDate(2026, 10, 1));605 assert(trunc Date(d, DatePart.MONTH) == toDate(2026, 10, 1));606 assert(trunc Date(d, DatePart.WEEK) == toDate(2026, 10, 26));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)); 607 613 } 608 614 … … 643 649 * Returns: The d_time time as a string. 644 650 */ 645 public char[] t imeToString(d_time time, char[] format = ISO_FORMAT_TIME) {651 public char[] toString(d_time time, char[] format = ISO_FORMAT_TIME) { 646 652 int hour, minute, second, millisecond; 647 653 … … 684 690 } 685 691 unittest { 686 // Also tests toTime(int, int, int) and t imeToString(), splitTime()692 // Also tests toTime(int, int, int) and toString(), splitTime() 687 693 d_time t = toTime("12:01:02"); 688 assert(t imeToString(t) == "12:01:02");694 assert(toString(t) == "12:01:02"); 689 695 assert(t == toTime(12, 1, 2)); 690 696 // TODO: Allow for compact ISO times. … … 751 757 * Returns: The datepart of a d_time time. 752 758 */ 753 public int datePart(d_time time, DatePart datePart) {759 public int extract(d_time time, DatePart datePart) { 754 760 time = normTime(time); 755 761 switch (datePart) { … … 763 769 return cast(int)time % 1000; 764 770 default: 765 throw new InvalidDatePartException( toString(cast(int)datePart) ~771 throw new InvalidDatePartException(std.string.toString(cast(int)datePart) ~ 766 772 " is an invalid date part"); 767 773 } 768 774 } 769 775 unittest { 770 // Also tests toTimeDuration(), inc Time(DatePart, int), and incTime(duration)776 // Also tests toTimeDuration(), increment(DatePart, int), and increment(duration) 771 777 d_time t = toTime(1, 2, 3, 100); // 01:02:03.100 772 assert( datePart(t, DatePart.MILLISECOND) == 100);773 t = inc Time(t, DatePart.MINUTE, 125); // 03:07:03.100774 assert( datePart(t, DatePart.MINUTE) == 7);775 t = inc Time(t, toTimeDuration(-12, 20, 57, 50)); // 15:28:00.150776 assert( datePart(t, DatePart.HOUR) == 15);777 assert( datePart(t, DatePart.SECOND) == 0);778 assert(extract(t, DatePart.MILLISECOND) == 100); 779 t = increment(t, DatePart.MINUTE, 125); // 03:07:03.100 780 assert(extract(t, DatePart.MINUTE) == 7); 781 t = increment(t, toTimeDuration(-12, 20, 57, 50)); // 15:28:00.150 782 assert(extract(t, DatePart.HOUR) == 15); 783 assert(extract(t, DatePart.SECOND) == 0); 778 784 } 779 785 … … 788 794 * Returns: A d_time time. 789 795 */ 790 public d_time trunc Time(d_time time, DatePart datePart) {796 public d_time truncate(d_time time, DatePart datePart) { 791 797 time = normTime(time); 792 798 switch (datePart) { … … 798 804 return cast(d_time)(cast(int)(time / MSEC_PER_SEC) * MSEC_PER_SEC); 799 805 default: 800 throw new InvalidDatePartException( toString(cast(int)datePart) ~806 throw new InvalidDatePartException(std.string.toString(cast(int)datePart) ~ 801 807 " is an invalid date part"); 802 808 } … … 804 810 unittest { 805 811 d_time t = toTime(12, 13, 14, 15); 806 assert(trunc Time(t, DatePart.SECOND) == toTime("12:13:14"));807 assert(trunc Time(t, DatePart.MINUTE) == toTime("12:13:00"));808 assert(trunc Time(t, DatePart.HOUR) == toTime("12:00:00"));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")); 809 815 } 810 816 … … 820 826 * Returns: A d_time time. 821 827 */ 822 public d_time inc Time(d_time time, DatePart datePart, int count) {828 public d_time increment(d_time time, DatePart datePart, int count) { 823 829 switch (datePart) { 824 830 case DatePart.HOUR: … … 835 841 break; 836 842 default: 837 throw new InvalidDatePartException( toString(cast(int)datePart) ~843 throw new InvalidDatePartException(std.string.toString(cast(int)datePart) ~ 838 844 " is an invalid date part"); 839 845 } … … 851 857 * Returns: A d_time time. 852 858 */ 853 public d_time inc Time(d_time time, d_duration duration) {859 public d_time increment(d_time time, d_duration duration) { 854 860 time += cast(d_time)(duration.daysAndTime * MSEC_PER_DAY) % 855 861 MSEC_PER_DAY; … … 867 873 * Returns: The d_timestamp time as a string. 868 874 */ 869 public char[] t imeStampToString(d_timestamp timestamp,875 public char[] toString(d_timestamp timestamp, 870 876 char[] format = ISO_FORMAT_TIMESTAMP) { 871 877 assert(format == ISO_FORMAT_TIMESTAMP); 872 878 873 return dateToString(dateOfTimeStamp(timestamp), format[0..8]) ~ " " ~874 t imeToString(timeOfTimeStamp(timestamp), format[9..$]);879 return toString(dateOfTimeStamp(timestamp), format[0..8]) ~ " " ~ 880 toString(timeOfTimeStamp(timestamp), format[9..$]); 875 881 } 876 882 … … 910 916 unittest { 911 917 // Also tests toTimeStamp(int, int...), toTimeStamp(date, time), 912 // toTimeStamp(int), t imeStampToString(), and splitTimeStamp()918 // toTimeStamp(int), toString(), and splitTimeStamp() 913 919 d_timestamp ts = toTimeStamp("2006-03-19 11:42:00"); 914 920 assert(ts == toTimeStamp(toDate("2006-03-19"), toTime("11:42:00"))); 915 assert(t imeStampToString(toTimeStamp(0)) == "1970-01-01 00:00:00");921 assert(toString(toTimeStamp(0)) == "1970-01-01 00:00:00"); 916 922 d_date d; 917 923 d_time t; … … 1006 1012 * Returns: The datepart of a date/time. 1007 1013 */ 1008 public int datePart(d_timestamp timestamp, DatePart aDatePart) {1014 public int extract(d_timestamp timestamp, DatePart aDatePart) { 1009 1015 if (aDatePart == DatePart.EPOCH) { 1010 1016 return cast(int)((cast(double)timestamp + DATE_UNIX_EPOCH_OFFSET) * 1011 1017 SEC_PER_DAY); 1012 1018 } else if (aDatePart < DatePart.HOUR) { 1013 return datePart(dateOfTimeStamp(timestamp), aDatePart);1019 return extract(dateOfTimeStamp(timestamp), aDatePart); 1014 1020 } else { 1015 return datePart(timeOfTimeStamp(timestamp), aDatePart);1021 return extract(timeOfTimeStamp(timestamp), aDatePart); 1016 1022 } 1017 1023 } 1018 1024 unittest { 1019 1025 d_timestamp ts = toTimeStamp("2006-01-01 00:00:00"); 1020 ts = inc TimeStamp(ts, toDuration(1, 2, 3, 4, 5, 6, 7)); // 2006-03-04 04:05:06.0071021 assert( datePart(ts, DatePart.SECOND) == 6);1022 ts = inc TimeStamp(ts, DatePart.SECOND, -200); // 2006-03-04 04:01:46.0071023 assert( datePart(ts, DatePart.MINUTE) == 1);1024 ts = inc TimeStamp(ts, DatePart.HOUR, 50); // 2006-03-06 06:05:06.0071025 assert( datePart(ts, DatePart.HOUR) == 6);1026 ts = inc TimeStamp(ts, DatePart.WEEK, 1); // 2006-03-13 06:05:06.0071027 assert( datePart(ts, DatePart.YEARDAY) == 72);1028 assert( datePart(ts, DatePart.WEEKDAY) == 0);1029 assert( datePart(ts, DatePart.WEEK) == 11);1030 writefln(t imeStampToString(ts));1031 ts = inc TimeStamp(ts, DatePart.MONTH, -14); // 2005-01-13 06:05:06.0071032 writefln(t imeStampToString(ts));1033 assert( datePart(ts, DatePart.DAY) == 13);1034 assert( datePart(ts, DatePart.MONTH) == 1);1035 assert( datePart(ts, DatePart.YEAR) == 2005);1026 ts = increment(ts, toDuration(1, 2, 3, 4, 5, 6, 7)); // 2006-03-04 04:05:06.007 1027 assert(extract(ts, DatePart.SECOND) == 6); 1028 ts = increment(ts, DatePart.SECOND, -200); // 2006-03-04 04:01:46.007 1029 assert(extract(ts, DatePart.MINUTE) == 1); 1030 ts = increment(ts, DatePart.HOUR, 50); // 2006-03-06 06:05:06.007 1031 assert(extract(ts, DatePart.HOUR) == 6); 1032 ts = increment(ts, DatePart.WEEK, 1); // 2006-03-13 06:05:06.007 1033 assert(extract(ts, DatePart.YEARDAY) == 72); 1034 assert(extract(ts, DatePart.WEEKDAY) == 0); 1035 assert(extract(ts, DatePart.WEEK) == 11); 1036 writefln(toString(ts)); 1037 ts = increment(ts, DatePart.MONTH, -14); // 2005-01-13 06:05:06.007 1038 writefln(toString(ts)); 1039 assert(extract(ts, DatePart.DAY) == 13); 1040 assert(extract(ts, DatePart.MONTH) == 1); 1041 assert(extract(ts, DatePart.YEAR) == 2005); 1036 1042 } 1037 1043 … … 1046 1052 * Returns: A d_timestamp date/time. 1047 1053 */ 1048 public d_timestamp trunc TimeStamp(d_timestamp timestamp, DatePart datePart) {1054 public d_timestamp truncate(d_timestamp timestamp, DatePart datePart) { 1049 1055 if (datePart == DatePart.DAY) { 1050 1056 return cast(d_timestamp)(cast(int)timestamp); 1051 1057 } else { 1052 1058 if (datePart < DatePart.HOUR) { 1053 return toTimeStamp(trunc Date(dateOfTimeStamp(timestamp), datePart), 0);1059 return toTimeStamp(truncate(dateOfTimeStamp(timestamp), datePart), 0); 1054 1060 } else { 1055 1061 return toTimeStamp(dateOfTimeStamp(timestamp), 1056 trunc Time(timeOfTimeStamp(timestamp), datePart));1062 truncate(timeOfTimeStamp(timestamp), datePart)); 1057 1063 } 1058 1064 } … … 1060 1066 unittest { 1061 1067 d_timestamp ts = toTimeStamp("2006-03-19 12:26:42"); 1062 assert(trunc TimeStamp(ts, DatePart.MINUTE) == toTimeStamp("2006-03-19 12:26:00"));1063 assert(trunc TimeStamp(ts, DatePart.HOUR) == toTimeStamp("2006-03-19 12:00:00"));1064 assert(trunc TimeStamp(ts, DatePart.DAY) == toTimeStamp("2006-03-19 00:00:00"));1065 assert(trunc TimeStamp(ts, DatePart.WEEK) == toTimeStamp("2006-03-13 00:00:00"));1066 assert(trunc TimeStamp(ts, DatePart.MONTH) == toTimeStamp("2006-03-01 00:00:00"));1067 assert(trunc TimeStamp(ts, DatePart.QUARTER) == toTimeStamp("2006-01-01 00:00:00"));1068 assert(trunc TimeStamp(ts, DatePart.YEAR) == toTimeStamp("2006-01-01 00:00:00"));1069 assert(trunc TimeStamp(ts, DatePart.DECADE) == toTimeStamp("2000-01-01 00:00:00"));1070 assert(trunc TimeStamp(ts, DatePart.MILLENIA) == toTimeStamp("2000-01-01 00:00:00"));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")); 1071 1077 } 1072 1078 … … 1082 1088 * Returns: A d_time time. 1083 1089 */ 1084 public d_timestamp inc TimeStamp(d_timestamp timestamp, DatePart datePart, int count) {1090 public d_timestamp increment(d_timestamp timestamp, DatePart datePart, int count) { 1085 1091 if (datePart < DatePart.HOUR) { 1086 return toTimeStamp(inc Date(dateOfTimeStamp(timestamp), datePart, count),1092 return toTimeStamp(increment(dateOfTimeStamp(timestamp), datePart, count), 1087 1093 timeOfTimeStamp(timestamp)); 1088 1094 } else { … … 1101 1107 break; 1102 1108 default: 1103 throw new InvalidDatePartException( toString(cast(int)datePart) ~1109 throw new InvalidDatePartException(std.string.toString(cast(int)datePart) ~ 1104 1110 " is an invalid date part"); 1105 1111 } … … 1118 1124 * Returns: A d_timestamp date/time. 1119 1125 */ 1120 public d_timestamp inc TimeStamp(d_timestamp timestamp, d_duration duration) {1121 return inc TimeStamp(timestamp, DatePart.MONTH, duration.months) +1126 public d_timestamp increment(d_timestamp timestamp, d_duration duration) { 1127 return increment(timestamp, DatePart.MONTH, duration.months) + 1122 1128 cast(d_timestamp)duration.daysAndTime; 1123 1129 } … … 1184 1190 * Returns: The d_duration duration as a string. 1185 1191 */ 1186 public char[] durationToString(d_duration duration) {1192 public char[] toString(d_duration duration) { 1187 1193 assert(0); 1188 1194 } … … 1352 1358 * Returns: The datepart of an duration. 1353 1359 */ 1354 public int datePart(d_duration duration, DatePart datePart) {1360 public int extract(d_duration duration, DatePart datePart) { 1355 1361 if (datePart < DatePart.HOUR) { 1356 1362 switch (datePart) { … … 1370 1376 return cast(int)duration.daysAndTime; 1371 1377 default: 1372 throw new InvalidDatePartException( toString(cast(int)datePart) ~1378 throw new InvalidDatePartException(std.string.toString(cast(int)datePart) ~ 1373 1379 " is an invalid date part"); 1374 1380 } … … 1385 1391 return cast(int)((timePart * MSEC_PER_DAY) % 1000); 1386 1392 default: 1387 throw new InvalidDatePartException( toString(cast(int)datePart) ~1393 throw new InvalidDatePartException(std.string.toString(cast(int)datePart) ~ 1388 1394 " is an invalid date part"); 1389 1395 } … … 1405 1411 * Returns: A d_timestamp date/time. 1406 1412 */ 1407 public d_duration trunc Duration(d_duration duration, DatePart datePart) {1413 public d_duration truncate(d_duration duration, DatePart datePart) { 1408 1414 if (datePart < DatePart.WEEK) { 1409 1415 duration.daysAndTime = 0.0; … … 1445 1451 break; 1446 1452 default: 1447 throw new InvalidDatePartException( toString(cast(int)datePart) ~1453 throw new InvalidDatePartException(std.string.toString(cast(int)datePart) ~ 1448 1454 " is an invalid date part"); 1449 1455 } … … 1462 1468 * Returns: An d_duration duration. 1463 1469 */ 1464 public d_duration inc Duration(d_duration duration, DatePart datePart,1470 public d_duration increment(d_duration duration, DatePart datePart, 1465 1471 int count) { 1466 1472 switch (datePart) { … … 1499 1505 break; 1500 1506 default: 1501 throw new InvalidDatePartException( toString(cast(int)datePart) ~1507 throw new InvalidDatePartException(std.string.toString(cast(int)datePart) ~ 1502 1508 " is an invalid date part"); 1503 1509 } … … 1515 1521 * Returns: An d_duration date/time. 1516 1522 */ 1517 public d_duration inc Duration(d_duration duration, d_duration addduration) {1523 public d_duration increment(d_duration duration, d_duration addduration) { 1518 1524 duration.daysAndTime += addduration.daysAndTime; 1519 1525 duration.months += addduration.months; … … 1671 1677 writefln("%d-%d-%d", year, month, day); 1672 1678 writefln(weekDayOfDate(date)); 1673 writefln( dateToString(date));1679 writefln(toString(date)); 1674 1680 writefln(toDate(2001, 1, 1)); 1675 1681 branches/dateparse.d
r49 r50 620 620 tmask = maskDate(); 621 621 dtype = FieldType.DATE; 622 splitDate(inc Date(date.date(), DatePart.DAY, -1), datetime.year,622 splitDate(increment(date.date(), DatePart.DAY, -1), datetime.year, 623 623 datetime.month, datetime.day); 624 624 break; … … 633 633 tmask = maskDate(); 634 634 dtype = FieldType.DATE; 635 splitDate(inc Date(date.date(), DatePart.DAY, 1), datetime.year,635 splitDate(increment(date.date(), DatePart.DAY, 1), datetime.year, 636 636 datetime.month, datetime.day); 637 637 break;
