Создание, анализ ирефакторинг
Скачать 3.16 Mb.
|
443 63 public abstract Month getMonth(); 64 public abstract int getDayOfMonth(); 65 66 protected abstract Day getDayOfWeekForOrdinalZero(); 67 68 public DayDate plusDays(int days) { 69 return DayDateFactory.makeDate(getOrdinalDay() + days); 70 } 71 72 public DayDate plusMonths(int months) { 73 int thisMonthAsOrdinal = getMonth().toInt() - Month.JANUARY.toInt(); 74 int thisMonthAndYearAsOrdinal = 12 * getYear() + thisMonthAsOrdinal; 75 int resultMonthAndYearAsOrdinal = thisMonthAndYearAsOrdinal + months; 76 int resultYear = resultMonthAndYearAsOrdinal / 12; 77 int resultMonthAsOrdinal = resultMonthAndYearAsOrdinal % 12 + Month.JANUARY. toInt(); 78 Month resultMonth = Month.fromInt(resultMonthAsOrdinal); 79 int resultDay = correctLastDayOfMonth(getDayOfMonth(), resultMonth, resultYear); 80 return DayDateFactory.makeDate(resultDay, resultMonth, resultYear); 81 } 82 83 public DayDate plusYears(int years) { 84 int resultYear = getYear() + years; 85 int resultDay = correctLastDayOfMonth(getDayOfMonth(), getMonth(), resultYear); 86 return DayDateFactory.makeDate(resultDay, getMonth(), resultYear); 87 } 88 89 private int correctLastDayOfMonth(int day, Month month, int year) { 90 int lastDayOfMonth = DateUtil.lastDayOfMonth(month, year); 91 if (day > lastDayOfMonth) 92 day = lastDayOfMonth; 93 return day; 94 } 95 96 public DayDate getPreviousDayOfWeek(Day targetDayOfWeek) { 97 int offsetToTarget = targetDayOfWeek.toInt() - getDayOfWeek().toInt(); 98 if (offsetToTarget >= 0) 99 offsetToTarget -= 7; 100 return plusDays(offsetToTarget); 101 } 102 103 public DayDate getFollowingDayOfWeek(Day targetDayOfWeek) { 104 int offsetToTarget = targetDayOfWeek.toInt() - getDayOfWeek().toInt(); 105 if (offsetToTarget <= 0) 106 offsetToTarget += 7; 107 return plusDays(offsetToTarget); 108 } 109 110 public DayDate getNearestDayOfWeek(Day targetDayOfWeek) { 111 int offsetToThisWeeksTarget = targetDayOfWeek.toInt() - getDayOfWeek(). toInt(); 112 int offsetToFutureTarget = (offsetToThisWeeksTarget + 7) % 7; 113 int offsetToPreviousTarget = offsetToFutureTarget - 7; 114 продолжение 443 444 Приложение Б . org.jfree.date.SerialDate листинг Б .7 (продолжение) 115 if (offsetToFutureTarget > 3) 116 return plusDays(offsetToPreviousTarget); 117 else 118 return plusDays(offsetToFutureTarget); 119 } 120 121 public DayDate getEndOfMonth() { 122 Month month = getMonth(); 123 int year = getYear(); 124 int lastDay = DateUtil.lastDayOfMonth(month, year); 125 return DayDateFactory.makeDate(lastDay, month, year); 126 } 127 128 public Date toDate() { 129 final Calendar calendar = Calendar.getInstance(); 130 int ordinalMonth = getMonth().toInt() - Month.JANUARY.toInt(); 131 calendar.set(getYear(), ordinalMonth, getDayOfMonth(), 0, 0, 0); 132 return calendar.getTime(); 133 } 134 135 public String toString() { 136 return String.format(«%02d-%s-%d», getDayOfMonth(), getMonth(), getYear()); 137 } 138 139 public Day getDayOfWeek() { 140 Day startingDay = getDayOfWeekForOrdinalZero(); 141 int startingOffset = startingDay.toInt() - Day.SUNDAY.toInt(); 142 int ordinalOfDayOfWeek = (getOrdinalDay() + startingOffset) % 7; 143 return Day.fromInt(ordinalOfDayOfWeek + Day.SUNDAY.toInt()); 144 } 145 146 public int daysSince(DayDate date) { 147 return getOrdinalDay() - date.getOrdinalDay(); 148 } 149 150 public boolean isOn(DayDate other) { 151 return getOrdinalDay() == other.getOrdinalDay(); 152 } 153 154 public boolean isBefore(DayDate other) { 155 return getOrdinalDay() < other.getOrdinalDay(); 156 } 157 158 public boolean isOnOrBefore(DayDate other) { 159 return getOrdinalDay() <= other.getOrdinalDay(); 160 } 161 162 public boolean isAfter(DayDate other) { 163 return getOrdinalDay() > other.getOrdinalDay(); 164 } 444 org.jfree.date.SerialDate 445 165 166 public boolean isOnOrAfter(DayDate other) { 167 return getOrdinalDay() >= other.getOrdinalDay(); 168 } 169 170 public boolean isInRange(DayDate d1, DayDate d2) { 171 return isInRange(d1, d2, DateInterval.CLOSED); 172 } 173 174 public boolean isInRange(DayDate d1, DayDate d2, DateInterval interval) { 175 int left = Math.min(d1.getOrdinalDay(), d2.getOrdinalDay()); 176 int right = Math.max(d1.getOrdinalDay(), d2.getOrdinalDay()); 177 return interval.isIn(getOrdinalDay(), left, right); 178 } 179 } листинг Б .8 . Month.java (окончательная версия) 1 package org.jfree.date; 2 3 import java.text.DateFormatSymbols; 4 5 public enum Month { 6 JANUARY(1), FEBRUARY(2), MARCH(3), 7 APRIL(4), MAY(5), JUNE(6), 8 JULY(7), AUGUST(8), SEPTEMBER(9), 9 OCTOBER(10),NOVEMBER(11),DECEMBER(12); 10 private static DateFormatSymbols dateFormatSymbols = new DateFormatSymbols(); 11 private static final int[] LAST_DAY_OF_MONTH = 12 {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 13 14 private int index; 15 16 Month(int index) { 17 this.index = index; 18 } 19 20 public static Month fromInt(int monthIndex) { 21 for (Month m : Month.values()) { 22 if (m.index == monthIndex) 23 return m; 24 } 25 throw new IllegalArgumentException("Invalid month index " + monthIndex); 26 } 27 28 public int lastDay() { 29 return LAST_DAY_OF_MONTH[index]; 30 } 31 32 public int quarter() { 33 return 1 + (index - 1) / 3; 34 } продолжение 445 446 Приложение Б . org.jfree.date.SerialDate листинг Б .8 (продолжение) 35 36 public String toString() { 37 return dateFormatSymbols.getMonths()[index - 1]; 38 } 39 40 public String toShortString() { 41 return dateFormatSymbols.getShortMonths()[index - 1]; 42 } 43 44 public static Month parse(String s) { 45 s = s.trim(); 46 for (Month m : Month.values()) 47 if (m.matches(s)) 48 return m; 49 50 try { 51 return fromInt(Integer.parseInt(s)); 52 } 53 catch (NumberFormatException e) {} 54 throw new IllegalArgumentException(«Invalid month « + s); 55 } 56 57 private boolean matches(String s) { 58 return s.equalsIgnoreCase(toString()) || 59 s.equalsIgnoreCase(toShortString()); 60 } 61 62 public int toInt() { 63 return index; 64 } 65 } листинг Б .9 . Day.java (окончательная версия) 1 package org.jfree.date; 2 3 import java.util.Calendar; 4 import java.text.DateFormatSymbols; 5 6 public enum Day { 7 MONDAY(Calendar.MONDAY), 8 TUESDAY(Calendar.TUESDAY), 9 WEDNESDAY(Calendar.WEDNESDAY), 10 THURSDAY(Calendar.THURSDAY), 11 FRIDAY(Calendar.FRIDAY), 12 SATURDAY(Calendar.SATURDAY), 13 SUNDAY(Calendar.SUNDAY); 14 15 private final int index; 16 private static DateFormatSymbols dateSymbols = new DateFormatSymbols(); 17 446 org.jfree.date.SerialDate 447 18 Day(int day) { 19 index = day; 20 } 21 22 public static Day fromInt(int index) throws IllegalArgumentException { 23 for (Day d : Day.values()) 24 if (d.index == index) 25 return d; 26 throw new IllegalArgumentException( 27 String.format(«Illegal day index: %d.», index)); 28 } 29 30 public static Day parse(String s) throws IllegalArgumentException { 31 String[] shortWeekdayNames = 32 dateSymbols.getShortWeekdays(); 33 String[] weekDayNames = 34 dateSymbols.getWeekdays(); 35 36 s = s.trim(); 37 for (Day day : Day.values()) { 38 if (s.equalsIgnoreCase(shortWeekdayNames[day.index]) || 39 s.equalsIgnoreCase(weekDayNames[day.index])) { 40 return day; 41 } 42 } 43 throw new IllegalArgumentException( 44 String.format("%s is not a valid weekday string", s)); 45 } 46 47 public String toString() { 48 return dateSymbols.getWeekdays()[index]; 49 } 50 51 public int toInt() { 52 return index; 53 } 54 } листинг Б .10 . DateInterval.java (окончательная версия) 1 package org.jfree.date; 2 3 public enum DateInterval { 4 OPEN { 5 public boolean isIn(int d, int left, int right) { 6 return d > left && d < right; 7 } 8 }, 9 CLOSED_LEFT { 10 public boolean isIn(int d, int left, int right) { 11 return d >= left && d < right; 12 } продолжение 447 448 Приложение Б . org.jfree.date.SerialDate 13 }, 14 CLOSED_RIGHT { 15 public boolean isIn(int d, int left, int right) { 16 return d > left && d <= right; 17 } 18 }, 19 CLOSED { 20 public boolean isIn(int d, int left, int right) { 21 return d >= left && d <= right; 22 } 23 }; 24 25 public abstract boolean isIn(int d, int left, int right); 26 } листинг Б .11 . WeekInMonth.java (окончательная версия) 1 package org.jfree.date; 2 3 public enum WeekInMonth { 4 FIRST(1), SECOND(2), THIRD(3), FOURTH(4), LAST(0); 5 private final int index; 6 7 WeekInMonth(int index) { 8 this.index = index; 9 } 10 11 public int toInt() { 12 return index; 13 } 14 } листинг Б .12 . WeekdayRange.java (окончательная версия) 1 package org.jfree.date; 2 3 public enum WeekdayRange { 4 LAST, NEAREST, NEXT 5 } листинг Б .13 . DateUtil.java (окончательная версия) 1 package org.jfree.date; 2 3 import java.text.DateFormatSymbols; 4 5 public class DateUtil { 6 private static DateFormatSymbols dateFormatSymbols = new DateFormatSymbols(); 7 8 public static String[] getMonthNames() { 9 return dateFormatSymbols.getMonths(); 10 } 11 448 org.jfree.date.SerialDate 449 12 public static boolean isLeapYear(int year) { 13 boolean fourth = year % 4 == 0; 14 boolean hundredth = year % 100 == 0; 15 boolean fourHundredth = year % 400 == 0; 16 return fourth && (!hundredth || fourHundredth); 17 } 18 19 public static int lastDayOfMonth(Month month, int year) { 20 if (month == Month.FEBRUARY && isLeapYear(year)) 21 return month.lastDay() + 1; 22 else 23 return month.lastDay(); 24 } 25 26 public static int leapYearCount(int year) { 27 int leap4 = (year - 1896) / 4; 28 int leap100 = (year - 1800) / 100; 29 int leap400 = (year - 1600) / 400; 30 return leap4 - leap100 + leap400; 31 } 32 } листинг Б .14 . DayDateFactory.java (окончательная версия) 1 package org.jfree.date; 2 3 public abstract class DayDateFactory { 4 private static DayDateFactory factory = new SpreadsheetDateFactory(); 5 public static void setInstance(DayDateFactory factory) { 6 DayDateFactory.factory = factory; 7 } 8 9 protected abstract DayDate _makeDate(int ordinal); 10 protected abstract DayDate _makeDate(int day, Month month, int year); 11 protected abstract DayDate _makeDate(int day, int month, int year); 12 protected abstract DayDate _makeDate(java.util.Date date); 13 protected abstract int _getMinimumYear(); 14 protected abstract int _getMaximumYear(); 15 16 public static DayDate makeDate(int ordinal) { 17 return factory._makeDate(ordinal); 18 } 19 20 public static DayDate makeDate(int day, Month month, int year) { 21 return factory._makeDate(day, month, year); 22 } 23 24 public static DayDate makeDate(int day, int month, int year) { 25 return factory._makeDate(day, month, year); 26 } 27 28 public static DayDate makeDate(java.util.Date date) { продолжение 449 450 Приложение Б . org.jfree.date.SerialDate листинг Б .14 (продолжение) 29 return factory._makeDate(date); 30 } 31 32 public static int getMinimumYear() { 33 return factory._getMinimumYear(); 34 } 35 36 public static int getMaximumYear() { 37 return factory._getMaximumYear(); 38 } 39 } листинг Б .15 . SpreadsheetDateFactory.java (окончательная версия) 1 package org.jfree.date; 2 3 import java.util.*; 4 5 public class SpreadsheetDateFactory extends DayDateFactory { 6 public DayDate _makeDate(int ordinal) { 7 return new SpreadsheetDate(ordinal); 8 } 9 10 public DayDate _makeDate(int day, Month month, int year) { 11 return new SpreadsheetDate(day, month, year); 12 } 13 14 public DayDate _makeDate(int day, int month, int year) { 15 return new SpreadsheetDate(day, month, year); 16 } 17 18 public DayDate _makeDate(Date date) { 19 final GregorianCalendar calendar = new GregorianCalendar(); 20 calendar.setTime(date); 21 return new SpreadsheetDate( 22 calendar.get(Calendar.DATE), 23 Month.fromInt(calendar.get(Calendar.MONTH) + 1), 24 calendar.get(Calendar.YEAR)); 25 } 26 27 protected int _getMinimumYear() { 28 return SpreadsheetDate.MINIMUM_YEAR_SUPPORTED; 29 } 30 31 protected int _getMaximumYear() { 32 return SpreadsheetDate.MAXIMUM_YEAR_SUPPORTED; 33 } 34 } 450 org.jfree.date.SerialDate 451 листинг Б .16 . SpreadsheetDate.java (окончательная версия) 1 /* ======================================================================== 2 * JCommon : библиотека классов общего назначения для платформы Java(tm) 3 * ======================================================================== 4 * 5 * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors. 6 * 52 * 53 */ 54 55 package org.jfree.date; 56 57 import static org.jfree.date.Month.FEBRUARY; 58 59 import java.util.*; 60 61 /** 62 * Представляет дату с использованием целого числа, по аналогии с реализацией 63 * в Microsoft Excel. Поддерживаемый диапазон дат: 64 * с 1 января 1900 по 31 декабря 9999. 65 * 66 * Учтите, что в Excel существует намеренная ошибка, вследствие которой год 67 * 1900 считается високосным, тогда как в действительности он таковым не является. 68 * Дополнительная информация приведена на сайте Microsoft в статье Q181370: 69 * 70 * http://support.microsoft.com/support/kb/articles/Q181/3/70.asp 71 * 72 * По правилам Excel 1 января 1900 = 1. По правилам этого класса 73 * 1 января 1900 = 2. 74 * В результате номер дня этого класса будет отличаться от номера Excel 75 * в январе и феврале 1900...но затем Excel прибавляет лишний день 76 * (29 февраля 1900, который в действительности не существует!), и с этого 77 * момента нумерация дней совпадает. 78 * 79 * @author David Gilbert 80 */ 81 public class SpreadsheetDate extends DayDate { 82 public static final int EARLIEST_DATE_ORDINAL = 2; // 1/1/1900 83 public static final int LATEST_DATE_ORDINAL = 2958465; // 12/31/9999 84 public static final int MINIMUM_YEAR_SUPPORTED = 1900; 85 public static final int MAXIMUM_YEAR_SUPPORTED = 9999; 86 static final int[] AGGREGATE_DAYS_TO_END_OF_PRECEDING_MONTH = 87 {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}; 88 static final int[] LEAP_YEAR_AGGREGATE_DAYS_TO_END_OF_PRECEDING_MONTH = 89 {0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}; 90 91 private int ordinalDay; 92 private int day; 93 private Month month; 94 private int year; продолжение 451 452 Приложение Б . org.jfree.date.SerialDate листинг Б .16 (продолжение) 95 96 public SpreadsheetDate(int day, Month month, int year) { 97 if (year < MINIMUM_YEAR_SUPPORTED || year > MAXIMUM_YEAR_SUPPORTED) 98 throw new IllegalArgumentException( 99 "The 'year' argument must be in range " + 100 MINIMUM_YEAR_SUPPORTED + " to " + MAXIMUM_YEAR_SUPPORTED + "."); 101 if (day < 1 || day > DateUtil.lastDayOfMonth(month, year)) 102 throw new IllegalArgumentException("Invalid 'day' argument."); 103 104 this.year = year; 105 this.month = month; 106 this.day = day; 107 ordinalDay = calcOrdinal(day, month, year); 108 } 109 110 public SpreadsheetDate(int day, int month, int year) { 111 this(day, Month.fromInt(month), year); 112 } 113 114 public SpreadsheetDate(int serial) { 115 if (serial < EARLIEST_DATE_ORDINAL || serial > LATEST_DATE_ORDINAL) 116 throw new IllegalArgumentException( 117 "SpreadsheetDate: Serial must be in range 2 to 2958465."); 118 119 ordinalDay = serial; 120 calcDayMonthYear(); 121 } 122 123 public int getOrdinalDay() { 124 return ordinalDay; 125 } 126 127 public int getYear() { 128 return year; 129 } 130 131 public Month getMonth() { 132 return month; 133 } 134 135 public int getDayOfMonth() { 136 return day; 137 } 138 139 protected Day getDayOfWeekForOrdinalZero() {return Day.SATURDAY;} 140 141 public boolean equals(Object object) { 142 if (!(object instanceof DayDate)) 143 return false; 144 452 org.jfree.date.SerialDate 453 145 DayDate date = (DayDate) object; 146 return date.getOrdinalDay() == getOrdinalDay(); 147 } 148 149 public int hashCode() { 150 return getOrdinalDay(); 151 } 152 153 public int compareTo(Object other) { 154 return daysSince((DayDate) other); 155 } 156 157 private int calcOrdinal(int day, Month month, int year) { 158 int leapDaysForYear = DateUtil.leapYearCount(year - 1); 159 int daysUpToYear = (year - MINIMUM_YEAR_SUPPORTED) * 365 + leapDaysForYear; 160 int daysUpToMonth = AGGREGATE_DAYS_TO_END_OF_PRECEDING_MONTH[month.toInt()]; 161 if (DateUtil.isLeapYear(year) && month.toInt() > FEBRUARY.toInt()) 162 daysUpToMonth++; 163 int daysInMonth = day - 1; 164 return daysUpToYear + daysUpToMonth + daysInMonth + EARLIEST_DATE_ORDINAL; 165 } 166 167 private void calcDayMonthYear() { 168 int days = ordinalDay - EARLIEST_DATE_ORDINAL; 169 int overestimatedYear = MINIMUM_YEAR_SUPPORTED + days / 365; 170 int nonleapdays = days - DateUtil.leapYearCount(overestimatedYear); 171 int underestimatedYear = MINIMUM_YEAR_SUPPORTED + nonleapdays / 365; 172 173 year = huntForYearContaining(ordinalDay, underestimatedYear); 174 int firstOrdinalOfYear = firstOrdinalOfYear(year); 175 month = huntForMonthContaining(ordinalDay, firstOrdinalOfYear); 176 day = ordinalDay - firstOrdinalOfYear - daysBeforeThisMonth(month.toInt()); 177 } 178 179 private Month huntForMonthContaining(int anOrdinal, int firstOrdinalOfYear) { 180 int daysIntoThisYear = anOrdinal - firstOrdinalOfYear; 181 int aMonth = 1; 182 while (daysBeforeThisMonth(aMonth) < daysIntoThisYear) 183 aMonth++; 184 185 return Month.fromInt(aMonth - 1); 186 } 187 188 private int daysBeforeThisMonth(int aMonth) { 189 if (DateUtil.isLeapYear(year)) 190 return LEAP_YEAR_AGGREGATE_DAYS_TO_END_OF_PRECEDING_MONTH[aMonth] - 1; 191 else 192 return AGGREGATE_DAYS_TO_END_OF_PRECEDING_MONTH[aMonth] - 1; 193 } 194 195 private int huntForYearContaining(int anOrdinalDay, int startingYear) { продолжение 453 |