001 package org.hackystat.utilities.time.period; 002 003 import java.text.SimpleDateFormat; 004 import java.util.ArrayList; 005 import java.util.Calendar; 006 import java.util.List; 007 import java.util.Locale; 008 009 import javax.xml.datatype.XMLGregorianCalendar; 010 011 /** 012 * Provides the Month abstract data type, which represents the collection of Week and Day 013 * instances in a given month. 014 * 015 * The Calendar is forced to Locale.US to ensure constant week boundaries. 016 * 017 * @author Hongbing Kou 018 */ 019 public class Month implements TimePeriod { 020 /** Calendar year. */ 021 private int year; 022 /** Calendar month. */ 023 private int month; 024 /** Number of days in this month. */ 025 private int numOfDays; 026 /** First day of the month. */ 027 private Day firstDay; 028 /** Last day of the month. */ 029 private Day lastDay; 030 /** Days' list in a month. */ 031 private List<Day> days; 032 033 /** 034 * Creates a Month instance for the given year and month. 035 * 036 * @param year The calendar year, such as 2004. 037 * @param month The zero-based calendar month, such as 0 (January) or 11 (December). 038 */ 039 public Month(int year, int month) { 040 this.year = year; 041 this.month = month; 042 043 Calendar cal = Calendar.getInstance(Locale.US); 044 cal.set(Calendar.DAY_OF_MONTH, 1); 045 cal.set(Calendar.YEAR, this.year); 046 cal.set(Calendar.MONTH, this.month); 047 048 this.numOfDays = cal.getActualMaximum(Calendar.DAY_OF_MONTH); 049 this.firstDay = Day.getInstance(year, month, 1); 050 this.lastDay = Day.getInstance(year, month, this.numOfDays); 051 052 this.days = new ArrayList<Day>(); 053 for (int i = 0; i < this.numOfDays; i++) { 054 this.days.add(Day.getInstance(year, month, i)); 055 } 056 } 057 058 /** 059 * Returns the Month instance corresponding to the passed XMLGregorianCalendar instance. 060 * @param xmlDay The XMLGregorianCalendar date. 061 */ 062 public Month(XMLGregorianCalendar xmlDay) { 063 this(xmlDay.getYear(), xmlDay.getMonth() - 1); 064 } 065 066 /** 067 * Returns the year associated with this Month. 068 * 069 * @return The year, such as 2004. 070 */ 071 public int getYear() { 072 return this.year; 073 } 074 075 /** 076 * Returns the zero-based month associated with this Month. 077 * 078 * @return The month, such as 0 (January) or 11 (December). 079 */ 080 public int getMonth() { 081 return this.month; 082 } 083 084 /** 085 * Returns the first Day instance associated with this Month. 086 * 087 * @return First Day of this Month. 088 */ 089 public Day getFirstDay() { 090 return this.firstDay; 091 } 092 093 /** 094 * Returns the Week instance associated with the first day in this Month. 095 * Note that the Week instance may include Day instances from the prior Month. 096 * 097 * @return The Week instance that includes the first Day of this Month. 098 */ 099 public Week getFirstWeekInMonth() { 100 return new Week(this.firstDay); 101 } 102 103 /** 104 * Returns the last Day instance associated with this Month. 105 * 106 * @return Last day of the month. 107 */ 108 public Day getLastDay() { 109 return this.lastDay; 110 } 111 112 /** 113 * Returns the Week instance associated with the last Day of this Month. 114 * Note that the Week instance may include Day instances from the next Month. 115 * 116 * @return Last week in the month. 117 */ 118 public Week getLastWeekInMonth() { 119 return new Week(this.lastDay); 120 } 121 122 /** 123 * Returns the number of days in this Month. 124 * 125 * @return Days in this month. 126 */ 127 public int getNumOfDays() { 128 return this.numOfDays; 129 } 130 131 /** 132 * Compares two Month instances. 133 * 134 * @param o Another month object. 135 * @return Comparison result. 136 */ 137 public int compareTo(Object o) { 138 Month month = (Month) o; 139 140 if (this.year == month.year) { 141 return this.month - month.month; 142 } 143 else { 144 return this.year - month.year; 145 } 146 } 147 148 /** 149 * Returns the Month instance prior to this Month. 150 * 151 * @return Previous month. 152 */ 153 public Month dec() { 154 if (this.month == 0) { 155 return new Month(this.year - 1, 11); 156 } 157 else { 158 return new Month(this.year, this.month - 1); 159 } 160 } 161 162 /** 163 * Returns the Month instance after this Month. 164 * 165 * @return Next month. 166 */ 167 public Month inc() { 168 if (this.month == 11) { 169 return new Month(this.year + 1, 0); 170 } 171 else { 172 return new Month(this.year, this.month + 1); 173 } 174 } 175 176 /** 177 * Hash code of this Month. 178 * 179 * @return Month's hashcode. 180 */ 181 @Override 182 public int hashCode() { 183 String monthString = "" + this.year + "" + this.month; 184 return monthString.hashCode(); 185 } 186 187 /** 188 * Returns true if the passed object is a month and is equal to this Month. 189 * 190 * @param obj Any object. 191 * @return True if two months are the equal. 192 */ 193 @Override 194 public boolean equals(Object obj) { 195 return ((obj instanceof Month) && 196 (this.year == ((Month) obj).year && this.month == ((Month) obj).month)); 197 } 198 199 /** 200 * String representation of this Month. 201 * 202 * @return Month string. 203 */ 204 @Override 205 public String toString() { 206 SimpleDateFormat formatter = new SimpleDateFormat("MMM-yyyy", Locale.US); 207 Day day = Day.getInstance(this.year, this.month, 1); 208 return formatter.format(day.getDate()); 209 } 210 211 /** 212 * Returns a list of Day instances from the first Day to the last Day in this Month. 213 * 214 * @return A sorted list of the Days in this Month. 215 */ 216 public List<Day> getDays() { 217 return this.days; 218 } 219 220 221 }