1 16 package org.apache.commons.lang.time; 17 18 import java.text.ParseException ; 19 import java.text.ParsePosition ; 20 import java.text.SimpleDateFormat ; 21 import java.util.Calendar ; 22 import java.util.Date ; 23 import java.util.Iterator ; 24 import java.util.NoSuchElementException ; 25 import java.util.TimeZone ; 26 27 39 public class DateUtils { 40 41 44 public static final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone("GMT"); 45 49 public static final long MILLIS_PER_SECOND = 1000; 50 54 public static final long MILLIS_PER_MINUTE = 60 * MILLIS_PER_SECOND; 55 59 public static final long MILLIS_PER_HOUR = 60 * MILLIS_PER_MINUTE; 60 64 public static final long MILLIS_PER_DAY = 24 * MILLIS_PER_HOUR; 65 66 70 public final static int SEMI_MONTH = 1001; 71 72 private static final int[][] fields = { 73 {Calendar.MILLISECOND}, 74 {Calendar.SECOND}, 75 {Calendar.MINUTE}, 76 {Calendar.HOUR_OF_DAY, Calendar.HOUR}, 77 {Calendar.DATE, Calendar.DAY_OF_MONTH, Calendar.AM_PM 78 79 }, 80 {Calendar.MONTH, DateUtils.SEMI_MONTH}, 81 {Calendar.YEAR}, 82 {Calendar.ERA}}; 83 84 87 public final static int RANGE_WEEK_SUNDAY = 1; 88 89 92 public final static int RANGE_WEEK_MONDAY = 2; 93 94 97 public final static int RANGE_WEEK_RELATIVE = 3; 98 99 102 public final static int RANGE_WEEK_CENTER = 4; 103 104 107 public final static int RANGE_MONTH_SUNDAY = 5; 108 109 112 public final static int RANGE_MONTH_MONDAY = 6; 113 114 122 public DateUtils() { 123 } 124 125 139 public static boolean isSameDay(Date date1, Date date2) { 140 if (date1 == null || date2 == null) { 141 throw new IllegalArgumentException ("The date must not be null"); 142 } 143 Calendar cal1 = Calendar.getInstance(); 144 cal1.setTime(date1); 145 Calendar cal2 = Calendar.getInstance(); 146 cal2.setTime(date2); 147 return isSameDay(cal1, cal2); 148 } 149 150 163 public static boolean isSameDay(Calendar cal1, Calendar cal2) { 164 if (cal1 == null || cal2 == null) { 165 throw new IllegalArgumentException ("The date must not be null"); 166 } 167 return (cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA) && 168 cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) && 169 cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR)); 170 } 171 172 184 public static boolean isSameInstant(Date date1, Date date2) { 185 if (date1 == null || date2 == null) { 186 throw new IllegalArgumentException ("The date must not be null"); 187 } 188 return date1.getTime() == date2.getTime(); 189 } 190 191 202 public static boolean isSameInstant(Calendar cal1, Calendar cal2) { 203 if (cal1 == null || cal2 == null) { 204 throw new IllegalArgumentException ("The date must not be null"); 205 } 206 return cal1.getTime().getTime() == cal2.getTime().getTime(); 207 } 208 209 222 public static boolean isSameLocalTime(Calendar cal1, Calendar cal2) { 223 if (cal1 == null || cal2 == null) { 224 throw new IllegalArgumentException ("The date must not be null"); 225 } 226 return (cal1.get(Calendar.MILLISECOND) == cal2.get(Calendar.MILLISECOND) && 227 cal1.get(Calendar.SECOND) == cal2.get(Calendar.SECOND) && 228 cal1.get(Calendar.MINUTE) == cal2.get(Calendar.MINUTE) && 229 cal1.get(Calendar.HOUR) == cal2.get(Calendar.HOUR) && 230 cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR) && 231 cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) && 232 cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA) && 233 cal1.getClass() == cal2.getClass()); 234 } 235 236 250 public static Date parseDate(String str, String [] parsePatterns) throws ParseException { 251 if (str == null || parsePatterns == null) { 252 throw new IllegalArgumentException ("Date and Patterns must not be null"); 253 } 254 255 SimpleDateFormat parser = null; 256 ParsePosition pos = new ParsePosition (0); 257 for (int i = 0; i < parsePatterns.length; i++) { 258 if (i == 0) { 259 parser = new SimpleDateFormat (parsePatterns[0]); 260 } else { 261 parser.applyPattern(parsePatterns[i]); 262 } 263 pos.setIndex(0); 264 Date date = parser.parse(str, pos); 265 if (date != null && pos.getIndex() == str.length()) { 266 return date; 267 } 268 } 269 throw new ParseException ("Unable to parse the date: " + str, -1); 270 } 271 272 301 public static Date round(Date date, int field) { 302 if (date == null) { 303 throw new IllegalArgumentException ("The date must not be null"); 304 } 305 Calendar gval = Calendar.getInstance(); 306 gval.setTime(date); 307 modify(gval, field, true); 308 return gval.getTime(); 309 } 310 311 339 public static Calendar round(Calendar date, int field) { 340 if (date == null) { 341 throw new IllegalArgumentException ("The date must not be null"); 342 } 343 Calendar rounded = (Calendar ) date.clone(); 344 modify(rounded, field, true); 345 return rounded; 346 } 347 348 378 public static Date round(Object date, int field) { 379 if (date == null) { 380 throw new IllegalArgumentException ("The date must not be null"); 381 } 382 if (date instanceof Date ) { 383 return round((Date ) date, field); 384 } else if (date instanceof Calendar ) { 385 return round((Calendar ) date, field).getTime(); 386 } else { 387 throw new ClassCastException ("Could not round " + date); 388 } 389 } 390 391 408 public static Date truncate(Date date, int field) { 409 if (date == null) { 410 throw new IllegalArgumentException ("The date must not be null"); 411 } 412 Calendar gval = Calendar.getInstance(); 413 gval.setTime(date); 414 modify(gval, field, false); 415 return gval.getTime(); 416 } 417 418 434 public static Calendar truncate(Calendar date, int field) { 435 if (date == null) { 436 throw new IllegalArgumentException ("The date must not be null"); 437 } 438 Calendar truncated = (Calendar ) date.clone(); 439 modify(truncated, field, false); 440 return truncated; 441 } 442 443 463 public static Date truncate(Object date, int field) { 464 if (date == null) { 465 throw new IllegalArgumentException ("The date must not be null"); 466 } 467 if (date instanceof Date ) { 468 return truncate((Date ) date, field); 469 } else if (date instanceof Calendar ) { 470 return truncate((Calendar ) date, field).getTime(); 471 } else { 472 throw new ClassCastException ("Could not truncate " + date); 473 } 474 } 475 476 485 private static void modify(Calendar val, int field, boolean round) { 486 if (val.get(Calendar.YEAR) > 280000000) { 487 throw new ArithmeticException ("Calendar value too large for accurate calculations"); 488 } 489 490 boolean roundUp = false; 491 for (int i = 0; i < fields.length; i++) { 492 for (int j = 0; j < fields[i].length; j++) { 493 if (fields[i][j] == field) { 494 if (round && roundUp) { 496 if (field == DateUtils.SEMI_MONTH) { 497 if (val.get(Calendar.DATE) == 1) { 501 val.add(Calendar.DATE, 15); 502 } else { 503 val.add(Calendar.DATE, -15); 504 val.add(Calendar.MONTH, 1); 505 } 506 } else { 507 val.add(fields[i][0], 1); 510 } 511 } 512 return; 513 } 514 } 515 int offset = 0; 517 boolean offsetSet = false; 518 switch (field) { 520 case DateUtils.SEMI_MONTH: 521 if (fields[i][0] == Calendar.DATE) { 522 offset = val.get(Calendar.DATE) - 1; 526 if (offset >= 15) { 529 offset -= 15; 530 } 531 roundUp = offset > 7; 533 offsetSet = true; 534 } 535 break; 536 case Calendar.AM_PM: 537 if (fields[i][0] == Calendar.HOUR_OF_DAY) { 538 offset = val.get(Calendar.HOUR_OF_DAY); 541 if (offset >= 12) { 542 offset -= 12; 543 } 544 roundUp = offset > 6; 545 offsetSet = true; 546 } 547 break; 548 } 549 if (!offsetSet) { 550 int min = val.getActualMinimum(fields[i][0]); 551 int max = val.getActualMaximum(fields[i][0]); 552 offset = val.get(fields[i][0]) - min; 554 roundUp = offset > ((max - min) / 2); 556 } 557 val.set(fields[i][0], val.get(fields[i][0]) - offset); 559 } 560 throw new IllegalArgumentException ("The field " + field + " is not supported"); 561 562 } 563 564 583 public static Iterator iterator(Date focus, int rangeStyle) { 584 if (focus == null) { 585 throw new IllegalArgumentException ("The date must not be null"); 586 } 587 Calendar gval = Calendar.getInstance(); 588 gval.setTime(focus); 589 return iterator(gval, rangeStyle); 590 } 591 592 613 public static Iterator iterator(Calendar focus, int rangeStyle) { 614 if (focus == null) { 615 throw new IllegalArgumentException ("The date must not be null"); 616 } 617 Calendar start = null; 618 Calendar end = null; 619 int startCutoff = Calendar.SUNDAY; 620 int endCutoff = Calendar.SATURDAY; 621 switch (rangeStyle) { 622 case RANGE_MONTH_SUNDAY: 623 case RANGE_MONTH_MONDAY: 624 start = truncate(focus, Calendar.MONTH); 626 end = (Calendar ) start.clone(); 628 end.add(Calendar.MONTH, 1); 629 end.add(Calendar.DATE, -1); 630 if (rangeStyle == RANGE_MONTH_MONDAY) { 632 startCutoff = Calendar.MONDAY; 633 endCutoff = Calendar.SUNDAY; 634 } 635 break; 636 case RANGE_WEEK_SUNDAY: 637 case RANGE_WEEK_MONDAY: 638 case RANGE_WEEK_RELATIVE: 639 case RANGE_WEEK_CENTER: 640 start = truncate(focus, Calendar.DATE); 642 end = truncate(focus, Calendar.DATE); 643 switch (rangeStyle) { 644 case RANGE_WEEK_SUNDAY: 645 break; 647 case RANGE_WEEK_MONDAY: 648 startCutoff = Calendar.MONDAY; 649 endCutoff = Calendar.SUNDAY; 650 break; 651 case RANGE_WEEK_RELATIVE: 652 startCutoff = focus.get(Calendar.DAY_OF_WEEK); 653 endCutoff = startCutoff - 1; 654 break; 655 case RANGE_WEEK_CENTER: 656 startCutoff = focus.get(Calendar.DAY_OF_WEEK) - 3; 657 endCutoff = focus.get(Calendar.DAY_OF_WEEK) + 3; 658 break; 659 } 660 break; 661 default: 662 throw new IllegalArgumentException ("The range style " + rangeStyle + " is not valid."); 663 } 664 if (startCutoff < Calendar.SUNDAY) { 665 startCutoff += 7; 666 } 667 if (startCutoff > Calendar.SATURDAY) { 668 startCutoff -= 7; 669 } 670 if (endCutoff < Calendar.SUNDAY) { 671 endCutoff += 7; 672 } 673 if (endCutoff > Calendar.SATURDAY) { 674 endCutoff -= 7; 675 } 676 while (start.get(Calendar.DAY_OF_WEEK) != startCutoff) { 677 start.add(Calendar.DATE, -1); 678 } 679 while (end.get(Calendar.DAY_OF_WEEK) != endCutoff) { 680 end.add(Calendar.DATE, 1); 681 } 682 return new DateIterator(start, end); 683 } 684 685 705 public static Iterator iterator(Object focus, int rangeStyle) { 706 if (focus == null) { 707 throw new IllegalArgumentException ("The date must not be null"); 708 } 709 if (focus instanceof Date ) { 710 return iterator((Date ) focus, rangeStyle); 711 } else if (focus instanceof Calendar ) { 712 return iterator((Calendar ) focus, rangeStyle); 713 } else { 714 throw new ClassCastException ("Could not iterate based on " + focus); 715 } 716 } 717 718 721 static class DateIterator implements Iterator { 722 private final Calendar endFinal; 723 private final Calendar spot; 724 725 731 DateIterator(Calendar startFinal, Calendar endFinal) { 732 super(); 733 this.endFinal = endFinal; 734 spot = startFinal; 735 spot.add(Calendar.DATE, -1); 736 } 737 738 743 public boolean hasNext() { 744 return spot.before(endFinal); 745 } 746 747 752 public Object next() { 753 if (spot.equals(endFinal)) { 754 throw new NoSuchElementException (); 755 } 756 spot.add(Calendar.DATE, 1); 757 return spot.clone(); 758 } 759 760 766 public void remove() { 767 throw new UnsupportedOperationException (); 768 } 769 } 770 771 775 780 public static final int MILLIS_IN_SECOND = 1000; 781 786 public static final int MILLIS_IN_MINUTE = 60 * 1000; 787 792 public static final int MILLIS_IN_HOUR = 60 * 60 * 1000; 793 798 public static final int MILLIS_IN_DAY = 24 * 60 * 60 * 1000; 799 800 } 801 | Popular Tags |