00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <stlib/Date.h>
00027 #include <stlib/String.h>
00028 #include <stlib/Stream.h>
00029
00030 static const unsigned char days_in_month[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
00031
00032 Date::Date(unsigned long julianDate)
00033 {
00034 julian_day_number = julianDate;
00035 }
00036
00037 Date::Date(int month, int day, int year)
00038 {
00039 julian_day_number = julianDay(month, day, year);
00040 }
00041
00042
00043 String *Date::className(void) const
00044 {
00045 return new String("Date");
00046 }
00047
00048
00049 Date *Date::today(void)
00050 {
00051 time_t timestamp = time(NULL);
00052 const struct tm* date = localtime(×tamp);
00053 return new Date(date->tm_mon+1, date->tm_mday, date->tm_year+1900);
00054 }
00055
00056
00058 int Date::month(void) const
00059 {
00060 int m, d, y;
00061 gregorianDate(m, d, y);
00062 return m;
00063 }
00064
00066 int Date::day(void) const
00067 {
00068 int m, d, y;
00069 gregorianDate(m, d, y);
00070 return d;
00071 }
00072
00074 int Date::year(void) const
00075 {
00076 int m, d, y;
00077 gregorianDate(m, d, y);
00078 return y;
00079 }
00080
00082 int Date::weekday(void) const
00083
00084
00085
00086
00087
00088 {
00089 return ((((julian_day_number + 1) % 7) + 6) % 7) + 1;
00090 }
00091
00093 int Date::century(void) const
00094 {
00095 return year() / 100;
00096 }
00097
00098 int Date::daysInMonth(int month, int year)
00099 {
00100 int dayCount = days_in_month[month];
00101 if (month == 2 && isLeapYear(year))
00102 dayCount = 29;
00103 return dayCount;
00104 }
00105
00106
00110 Date *Date::addDays(int dayCount)
00111 {
00112 return new Date(julian_day_number + dayCount);
00113 }
00114
00120 Date *Date::addMonths(int monthCount)
00121 {
00122 int m, d, y;
00123 gregorianDate(m, d, y);
00124 m += monthCount;
00125 while (m > 12) {
00126 m -= 12; y += 1;
00127 }
00128 int dm = daysInMonth(m, y);
00129 if (d > dm) d = dm;
00130 return new Date(m, d, y);
00131 }
00132
00136 Date *Date::addYears(int yearCount)
00137 {
00138 int m, d, y;
00139 gregorianDate(m, d, y);
00140 return new Date(m, d, y+yearCount);
00141 }
00142
00143 Date *Date::subtractDays(int dayCount)
00144 {
00145 return new Date(julian_day_number - dayCount);
00146 }
00147
00148 Date *Date::subtractMonths(int monthCount)
00149 {
00150 int m, d, y;
00151 gregorianDate(m, d, y);
00152 m -= monthCount;
00153 while (m <= 0) {
00154 m += 12; y -= 1;
00155 }
00156 int dm = daysInMonth(m, y);
00157 if (d > dm) d = dm;
00158 return new Date(m, d, y);
00159 }
00160
00161 Date *Date::subtractYears(int yearCount)
00162 {
00163 int m, d, y;
00164 gregorianDate(m, d, y);
00165 return new Date(m, d, y-yearCount);
00166 }
00167
00168 unsigned long Date::dayDifferenceFrom(Date *date)
00169 {
00170 unsigned long myDays, dateDays;
00171 myDays = asDays();
00172 dateDays = date->asDays();
00173 if (myDays > dateDays)
00174 return myDays - dateDays;
00175 return dateDays - myDays;
00176 }
00177
00178
00179 long Date::hash(void) const
00180 {
00181 return (long) julian_day_number;
00182 }
00183
00184 bool Date::isEqual(const Object *object) const
00185 {
00186 if (!object->className()->isEqual(this->className())) return false;
00187 return object->hash() == this->hash();
00188 }
00189
00190
00191 unsigned long Date::asDays(void) const
00192 {
00193 return julian_day_number;
00194 }
00195
00196
00197 void Date::printOn(Stream *stream) const
00198 {
00199
00200 String *dateStr;
00201 int m, d, y;
00202 gregorianDate(m, d, y);
00203 dateStr = String::format("%u.%u.%u", d, m, y);
00204 stream->nextPutAll(dateStr);
00205 }
00206
00207
00209 bool Date::isLeapYear(void) const
00210 {
00211 return isLeapYear(year());
00212 }
00213
00215 bool Date::isLeapYear(short year)
00216
00217 {
00218 return ((year & 3) == 0 && year % 100 != 0 || year % 400 == 0);
00219 }
00220
00221
00222
00223
00224
00225
00226
00227
00228 unsigned long Date::julianDay(int month, int day, int year)
00229 {
00230 unsigned long c, ya;
00231 if (month > 2) month -= 3;
00232 else {
00233 month += 9;
00234 year--;
00235 }
00236 ya = year % 100;
00237 c = year / 100;
00238 return ((146097*c)>>2) + ((1461*ya)>>2) + (153*month + 2)/5 + day + 1721119;
00239 }
00240
00241
00242
00243
00244
00245
00246
00247 void Date::gregorianDate(int &month, int &day, int &year) const
00248 {
00249 unsigned long j = julian_day_number - 1721119;
00250 unsigned long y = ((j<<2) - 1) / 146097;
00251 j = (j<<2) - 1 - 146097*y;
00252 unsigned long d = j>>2;
00253 j = ((d<<2) + 3) / 1461;
00254 d = (d<<2) + 3 - 1461*j;
00255 d = (d + 4)>>2;
00256 unsigned long m = (5*d - 3)/153;
00257 d = 5*d - 3 - 153*m;
00258 d = (d + 5)/5;
00259 y = 100*y + j;
00260 if (m < 10) m += 3;
00261 else {
00262 m -= 9;
00263 y++;
00264 }
00265 month = (int) m;
00266 day = (int) d;
00267 year = (int) y;
00268 }