1 58 59 package org.jfree.date; 60 61 import java.io.Serializable ; 62 import java.text.DateFormatSymbols ; 63 import java.text.SimpleDateFormat ; 64 import java.util.Calendar ; 65 import java.util.GregorianCalendar ; 66 67 86 public abstract class SerialDate implements Comparable , 87 Serializable , 88 MonthConstants { 89 90 91 private static final long serialVersionUID = -293716040467423637L; 92 93 94 public static final DateFormatSymbols 95 DATE_FORMAT_SYMBOLS = new SimpleDateFormat ().getDateFormatSymbols(); 96 97 98 public static final int SERIAL_LOWER_BOUND = 2; 99 100 101 public static final int SERIAL_UPPER_BOUND = 2958465; 102 103 104 public static final int MINIMUM_YEAR_SUPPORTED = 1900; 105 106 107 public static final int MAXIMUM_YEAR_SUPPORTED = 9999; 108 109 110 public static final int MONDAY = Calendar.MONDAY; 111 112 115 public static final int TUESDAY = Calendar.TUESDAY; 116 117 121 public static final int WEDNESDAY = Calendar.WEDNESDAY; 122 123 126 public static final int THURSDAY = Calendar.THURSDAY; 127 128 129 public static final int FRIDAY = Calendar.FRIDAY; 130 131 134 public static final int SATURDAY = Calendar.SATURDAY; 135 136 137 public static final int SUNDAY = Calendar.SUNDAY; 138 139 140 static final int[] LAST_DAY_OF_MONTH = 141 {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 142 143 144 static final int[] AGGREGATE_DAYS_TO_END_OF_MONTH = 145 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}; 146 147 148 static final int[] AGGREGATE_DAYS_TO_END_OF_PRECEDING_MONTH = 149 {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}; 150 151 152 static final int[] LEAP_YEAR_AGGREGATE_DAYS_TO_END_OF_MONTH = 153 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}; 154 155 158 static final int[] 159 LEAP_YEAR_AGGREGATE_DAYS_TO_END_OF_PRECEDING_MONTH = 160 {0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}; 161 162 163 public static final int FIRST_WEEK_IN_MONTH = 1; 164 165 166 public static final int SECOND_WEEK_IN_MONTH = 2; 167 168 169 public static final int THIRD_WEEK_IN_MONTH = 3; 170 171 172 public static final int FOURTH_WEEK_IN_MONTH = 4; 173 174 175 public static final int LAST_WEEK_IN_MONTH = 0; 176 177 178 public static final int INCLUDE_NONE = 0; 179 180 181 public static final int INCLUDE_FIRST = 1; 182 183 184 public static final int INCLUDE_SECOND = 2; 185 186 187 public static final int INCLUDE_BOTH = 3; 188 189 193 public static final int PRECEDING = -1; 194 195 199 public static final int NEAREST = 0; 200 201 205 public static final int FOLLOWING = 1; 206 207 208 private String description; 209 210 213 protected SerialDate() { 214 } 215 216 225 public static boolean isValidWeekdayCode(final int code) { 226 227 switch(code) { 228 case SUNDAY: 229 case MONDAY: 230 case TUESDAY: 231 case WEDNESDAY: 232 case THURSDAY: 233 case FRIDAY: 234 case SATURDAY: 235 return true; 236 default: 237 return false; 238 } 239 240 } 241 242 250 public static int stringToWeekdayCode(String s) { 251 252 final String [] shortWeekdayNames 253 = DATE_FORMAT_SYMBOLS.getShortWeekdays(); 254 final String [] weekDayNames = DATE_FORMAT_SYMBOLS.getWeekdays(); 255 256 int result = -1; 257 s = s.trim(); 258 for (int i = 0; i < weekDayNames.length; i++) { 259 if (s.equals(shortWeekdayNames[i])) { 260 result = i; 261 break; 262 } 263 if (s.equals(weekDayNames[i])) { 264 result = i; 265 break; 266 } 267 } 268 return result; 269 270 } 271 272 281 public static String weekdayCodeToString(final int weekday) { 282 283 final String [] weekdays = DATE_FORMAT_SYMBOLS.getWeekdays(); 284 return weekdays[weekday]; 285 286 } 287 288 293 public static String [] getMonths() { 294 295 return getMonths(false); 296 297 } 298 299 307 public static String [] getMonths(final boolean shortened) { 308 309 if (shortened) { 310 return DATE_FORMAT_SYMBOLS.getShortMonths(); 311 } 312 else { 313 return DATE_FORMAT_SYMBOLS.getMonths(); 314 } 315 316 } 317 318 326 public static boolean isValidMonthCode(final int code) { 327 328 switch(code) { 329 case JANUARY: 330 case FEBRUARY: 331 case MARCH: 332 case APRIL: 333 case MAY: 334 case JUNE: 335 case JULY: 336 case AUGUST: 337 case SEPTEMBER: 338 case OCTOBER: 339 case NOVEMBER: 340 case DECEMBER: 341 return true; 342 default: 343 return false; 344 } 345 346 } 347 348 355 public static int monthCodeToQuarter(final int code) { 356 357 switch(code) { 358 case JANUARY: 359 case FEBRUARY: 360 case MARCH: return 1; 361 case APRIL: 362 case MAY: 363 case JUNE: return 2; 364 case JULY: 365 case AUGUST: 366 case SEPTEMBER: return 3; 367 case OCTOBER: 368 case NOVEMBER: 369 case DECEMBER: return 4; 370 default: throw new IllegalArgumentException ( 371 "SerialDate.monthCodeToQuarter: invalid month code."); 372 } 373 374 } 375 376 386 public static String monthCodeToString(final int month) { 387 388 return monthCodeToString(month, false); 389 390 } 391 392 404 public static String monthCodeToString(final int month, 405 final boolean shortened) { 406 407 if (!isValidMonthCode(month)) { 409 throw new IllegalArgumentException ( 410 "SerialDate.monthCodeToString: month outside valid range."); 411 } 412 413 final String [] months; 414 415 if (shortened) { 416 months = DATE_FORMAT_SYMBOLS.getShortMonths(); 417 } 418 else { 419 months = DATE_FORMAT_SYMBOLS.getMonths(); 420 } 421 422 return months[month - 1]; 423 424 } 425 426 438 public static int stringToMonthCode(String s) { 439 440 final String [] shortMonthNames = DATE_FORMAT_SYMBOLS.getShortMonths(); 441 final String [] monthNames = DATE_FORMAT_SYMBOLS.getMonths(); 442 443 int result = -1; 444 s = s.trim(); 445 446 try { 448 result = Integer.parseInt(s); 449 } 450 catch (NumberFormatException e) { 451 } 453 454 if ((result < 1) || (result > 12)) { 456 for (int i = 0; i < monthNames.length; i++) { 457 if (s.equals(shortMonthNames[i])) { 458 result = i + 1; 459 break; 460 } 461 if (s.equals(monthNames[i])) { 462 result = i + 1; 463 break; 464 } 465 } 466 } 467 468 return result; 469 470 } 471 472 480 public static boolean isValidWeekInMonthCode(final int code) { 481 482 switch(code) { 483 case FIRST_WEEK_IN_MONTH: 484 case SECOND_WEEK_IN_MONTH: 485 case THIRD_WEEK_IN_MONTH: 486 case FOURTH_WEEK_IN_MONTH: 487 case LAST_WEEK_IN_MONTH: return true; 488 default: return false; 489 } 490 491 } 492 493 500 public static boolean isLeapYear(final int yyyy) { 501 502 if ((yyyy % 4) != 0) { 503 return false; 504 } 505 else if ((yyyy % 400) == 0) { 506 return true; 507 } 508 else if ((yyyy % 100) == 0) { 509 return false; 510 } 511 else { 512 return true; 513 } 514 515 } 516 517 527 public static int leapYearCount(final int yyyy) { 528 529 final int leap4 = (yyyy - 1896) / 4; 530 final int leap100 = (yyyy - 1800) / 100; 531 final int leap400 = (yyyy - 1600) / 400; 532 return leap4 - leap100 + leap400; 533 534 } 535 536 545 public static int lastDayOfMonth(final int month, final int yyyy) { 546 547 final int result = LAST_DAY_OF_MONTH[month]; 548 if (month != FEBRUARY) { 549 return result; 550 } 551 else if (isLeapYear(yyyy)) { 552 return result + 1; 553 } 554 else { 555 return result; 556 } 557 558 } 559 560 569 public static SerialDate addDays(final int days, final SerialDate base) { 570 571 final int serialDayNumber = base.toSerial() + days; 572 return SerialDate.createInstance(serialDayNumber); 573 574 } 575 576 588 public static SerialDate addMonths(final int months, 589 final SerialDate base) { 590 591 final int yy = (12 * base.getYYYY() + base.getMonth() + months - 1) 592 / 12; 593 final int mm = (12 * base.getYYYY() + base.getMonth() + months - 1) 594 % 12 + 1; 595 final int dd = Math.min( 596 base.getDayOfMonth(), SerialDate.lastDayOfMonth(mm, yy) 597 ); 598 return SerialDate.createInstance(dd, mm, yy); 599 600 } 601 602 611 public static SerialDate addYears(final int years, final SerialDate base) { 612 613 final int baseY = base.getYYYY(); 614 final int baseM = base.getMonth(); 615 final int baseD = base.getDayOfMonth(); 616 617 final int targetY = baseY + years; 618 final int targetD = Math.min( 619 baseD, SerialDate.lastDayOfMonth(baseM, targetY) 620 ); 621 622 return SerialDate.createInstance(targetD, baseM, targetY); 623 624 } 625 626 636 public static SerialDate getPreviousDayOfWeek(final int targetWeekday, 637 final SerialDate base) { 638 639 if (!SerialDate.isValidWeekdayCode(targetWeekday)) { 641 throw new IllegalArgumentException ( 642 "Invalid day-of-the-week code." 643 ); 644 } 645 646 final int adjust; 648 final int baseDOW = base.getDayOfWeek(); 649 if (baseDOW > targetWeekday) { 650 adjust = Math.min(0, targetWeekday - baseDOW); 651 } 652 else { 653 adjust = -7 + Math.max(0, targetWeekday - baseDOW); 654 } 655 656 return SerialDate.addDays(adjust, base); 657 658 } 659 660 670 public static SerialDate getFollowingDayOfWeek(final int targetWeekday, 671 final SerialDate base) { 672 673 if (!SerialDate.isValidWeekdayCode(targetWeekday)) { 675 throw new IllegalArgumentException ( 676 "Invalid day-of-the-week code." 677 ); 678 } 679 680 final int adjust; 682 final int baseDOW = base.getDayOfWeek(); 683 if (baseDOW > targetWeekday) { 684 adjust = 7 + Math.min(0, targetWeekday - baseDOW); 685 } 686 else { 687 adjust = Math.max(0, targetWeekday - baseDOW); 688 } 689 690 return SerialDate.addDays(adjust, base); 691 } 692 693 703 public static SerialDate getNearestDayOfWeek(final int targetDOW, 704 final SerialDate base) { 705 706 if (!SerialDate.isValidWeekdayCode(targetDOW)) { 708 throw new IllegalArgumentException ( 709 "Invalid day-of-the-week code." 710 ); 711 } 712 713 final int baseDOW = base.getDayOfWeek(); 715 int adjust = -Math.abs(targetDOW - baseDOW); 716 if (adjust >= 4) { 717 adjust = 7 - adjust; 718 } 719 if (adjust <= -4) { 720 adjust = 7 + adjust; 721 } 722 return SerialDate.addDays(adjust, base); 723 724 } 725 726 733 public SerialDate getEndOfCurrentMonth(final SerialDate base) { 734 final int last = SerialDate.lastDayOfMonth( 735 base.getMonth(), base.getYYYY() 736 ); 737 return SerialDate.createInstance(last, base.getMonth(), base.getYYYY()); 738 } 739 740 749 public static String weekInMonthToString(final int count) { 750 751 switch (count) { 752 case SerialDate.FIRST_WEEK_IN_MONTH : return "First"; 753 case SerialDate.SECOND_WEEK_IN_MONTH : return "Second"; 754 case SerialDate.THIRD_WEEK_IN_MONTH : return "Third"; 755 case SerialDate.FOURTH_WEEK_IN_MONTH : return "Fourth"; 756 case SerialDate.LAST_WEEK_IN_MONTH : return "Last"; 757 default : 758 return "SerialDate.weekInMonthToString(): invalid code."; 759 } 760 761 } 762 763 772 public static String relativeToString(final int relative) { 773 774 switch (relative) { 775 case SerialDate.PRECEDING : return "Preceding"; 776 case SerialDate.NEAREST : return "Nearest"; 777 case SerialDate.FOLLOWING : return "Following"; 778 default : return "ERROR : Relative To String"; 779 } 780 781 } 782 783 793 public static SerialDate createInstance(final int day, final int month, 794 final int yyyy) { 795 return new SpreadsheetDate(day, month, yyyy); 796 } 797 798 806 public static SerialDate createInstance(final int serial) { 807 return new SpreadsheetDate(serial); 808 } 809 810 817 public static SerialDate createInstance(final java.util.Date date) { 818 819 final GregorianCalendar calendar = new GregorianCalendar (); 820 calendar.setTime(date); 821 return new SpreadsheetDate(calendar.get(Calendar.DATE), 822 calendar.get(Calendar.MONTH) + 1, 823 calendar.get(Calendar.YEAR)); 824 825 } 826 827 834 public abstract int toSerial(); 835 836 842 public abstract java.util.Date toDate(); 843 844 851 public String getDescription() { 852 return this.description; 853 } 854 855 861 public void setDescription(final String description) { 862 this.description = description; 863 } 864 865 870 public String toString() { 871 return getDayOfMonth() + "-" + SerialDate.monthCodeToString(getMonth()) 872 + "-" + getYYYY(); 873 } 874 875 880 public abstract int getYYYY(); 881 882 887 public abstract int getMonth(); 888 889 894 public abstract int getDayOfMonth(); 895 896 901 public abstract int getDayOfWeek(); 902 903 914 public abstract int compare(SerialDate other); 915 916 925 public abstract boolean isOn(SerialDate other); 926 927 936 public abstract boolean isBefore(SerialDate other); 937 938 947 public abstract boolean isOnOrBefore(SerialDate other); 948 949 958 public abstract boolean isAfter(SerialDate other); 959 960 969 public abstract boolean isOnOrAfter(SerialDate other); 970 971 981 public abstract boolean isInRange(SerialDate d1, SerialDate d2); 982 983 995 public abstract boolean isInRange(SerialDate d1, SerialDate d2, 996 int include); 997 998 1007 public SerialDate getPreviousDayOfWeek(final int targetDOW) { 1008 return getPreviousDayOfWeek(targetDOW, this); 1009 } 1010 1011 1020 public SerialDate getFollowingDayOfWeek(final int targetDOW) { 1021 return getFollowingDayOfWeek(targetDOW, this); 1022 } 1023 1024 1031 public SerialDate getNearestDayOfWeek(final int targetDOW) { 1032 return getNearestDayOfWeek(targetDOW, this); 1033 } 1034 1035} 1036 | Popular Tags |