/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/NPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): */ /* * datetime.h * John Sun * 1/22/98 9:24:15 AM */ #ifndef __DATETIME_H_ #define __DATETIME_H_ #include #include #include #include #include #include #include #include #include "duration.h" #include "nscalutilexp.h" /* * Helper functions for use with JulianPtrArray */ NS_CAL_UTIL int DateTime_SortAscending( const void* v1, const void* v2 ); NS_CAL_UTIL int DateTime_SortDescending( const void* v1, const void* v2 ); class NS_CAL_UTIL DateTime { private: /*----------------------------- ** MEMBERS **---------------------------*/ #if 0 /* date formatting strings. Moved to nsCalFormatString class */ static UnicodeString ms_asPatterns[]; static UnicodeString ms_sISO8601Pattern; static UnicodeString ms_sISO8601LocalPattern; static UnicodeString ms_sISO8601TimeOnlyPattern; static UnicodeString ms_sISO8601DateOnlyPattern; static UnicodeString ms_sDefaultPattern; /* hashtable of simpleDateFormats vars and methods */ /* TODO: use for caching simpledateformats in other locales */ static SimpleDateFormat kDateFormats[]; static char* kDateFormatIDs[]; static const t_int32 kNumDateFormats; static Hashtable sdfHashtable; /* hashtable of date formats */ void initHashtable(); /* old data structures, used when static */ /*TimeZone * m_TimeZone;*/ static Locale * ms_Locale; static Locale ms_Locale; static ResourceBundle * ms_ResourceBundle; static GregorianCalendar ms_Calendar; static DateTime * invalidDate; /* singleton instance of an invalid Date */ static DateFormat ms_GMTISO8601DateFormat; static SimpleDateFormat * ms_DateFormat; #endif static ErrorCode staticStatus; static ErrorCode staticStatus2; static TimeZone * m_kGMTTimeZone; /* was const */ static TimeZone * m_kDefaultTimeZone; /* was const */ static TimeZone * ms_TimeZone; static GregorianCalendar * ms_Calendar; static SimpleDateFormat * ms_DateFormat; static t_bool m_Init; Date m_Date; /* like the long in java.util.Date */ /*----------------------------- ** PRIVATE METHODS **---------------------------*/ t_int8 compare(Date d); /** * Checks to see if static member data was initialized correctly. May remove later. */ static void CtorCore(); /** * helper method that encapsulates errorcode checking * while calling a get-field method * * @param aField a calendar field to get * @param timezone timezone returned field should be relevant to * @return the value of that field */ static t_int32 CalendarGetFieldHelper(Calendar::EDateFields aField, TimeZone * timezone = ms_TimeZone); /** * helper method that encapsulates errorcode checking * while calling a getTime() * (like calling ms_Calendar->getTime(ErrorCode);) * * @return the Date value of ms_Calendar */ static Date CalendarGetTimeHelper(); /** * helper method that encapsulates errorcode checking * while calling a setTime() * (like calling ms_Calendar->setTime(Date, ErrorCode);) * * @param d the Date value to set to ms_Calendar */ static void CalendarSetTimeHelper(Date d); #if 0 /** * parse the date string to get the Date value of the string * * @param s the UnicodeString to parse * @param locale the Locale to parse with * @return the Date value of the string */ static Date parse(UnicodeString & us, Locale & locale); /** * parse the date string to get the Date value of the string relative to a * a date-format pattern. * NOTE: Slow since creates new SimpleDateFormat * * @param pattern the date-format pattern to parse with * @param s the UnicodeString to parse * @param locale the Locale to parse with * @param timezone the TimeZone of the time string, default to ms_TimeZone * @return the Date value of the string */ static Date parseTime(UnicodeString & pattern, UnicodeString & time, Locale & locale, TimeZone * timezone = ms_TimeZone); #endif /** * parse the date string to get the Date value of the string relative to a * a date-format pattern. * * @param pattern the date-format pattern to parse with * @param s the UnicodeString to parse * @param timezone the TimeZone of the time string, default to ms_TimeZone * @return the Date value of the string */ static Date parseTime(UnicodeString & pattern, UnicodeString & time, TimeZone * timezone = ms_TimeZone); /* no locale */ /*static UnicodeString stringCheck(UnicodeString uc);*/ public: /** * correctly returns the number of days in a month, given * the month and a year. The rule for this method is the following: * Assume rule is Gregorian (pretend all dates after 1582). Use leap-year * rule every 4 years, except every 100 years, except every 400 years. * Thus 1700, 1800, 1900, 2100, 2200, 2300 are not leap years. * But 2000, 1600, 2400 are leap years. Of course, year divisible by 4, * but not divisible by 100 are leap years. * * @param iMonthNum the 1-based month value * @param iYearNum the year value (i.e. 1998, 1989, 2001) * @return the number of days in that month */ static t_int32 getMonthLength(t_int32 iMonthNum, t_int32 iYearNum); private: /** * Given an ISO8601 Date string, parse it to return the Date value. * Allows for passing in timezones. Thus if string is 19971225T112233 * and TimeZone is PST, then returned date value will be equal to * the number of milleseconds since the epoch (Jan 1, 1970 12:00 AM GMT) * on Dec 25, 1997 11:22:33 AM PST. * If the string is a UTC string (ends with a Z), the timezone is ignored * and the string is parsed relevant to the GMT timezone. * * Since the Calendar cannot recognize dates, before the epoch, * parseable DateTime strings with year value before 1970 will be set to 1970 * Thus a string 19671225T112233 will be changed to 19701225T112233. * This allows for parsing timezones with a start time before 1970. * Return -1 if the Date string is bogus. (i.e. bad parse, impossible values) * Also parses Dates, i.e. 19971110. Date values will have hours, minutes, * and seconds set to 0 in with respect to the timezone passed in. * * * @param us the UnicodeString to parse * @param timezone the TimeZone of the datetime is related to * @return the Date value of the string * @see IsParseable */ static Date parseISO8601(UnicodeString & us, TimeZone * timezone = ms_TimeZone); /** * The format workhorse method. Calls the SimpleDateformat * object to format pattern with respect to timezone * @param pattern pattern to format datetime to * @param aTimeZone timezone of datetime to format to * * @return UnicodeString */ UnicodeString strftimeNoLocale(UnicodeString& pattern, TimeZone * aTimeZone = ms_TimeZone); public: /*----------------------------- ** CONSTRUCTORS and DESTRUCTORS **---------------------------*/ /** * default constructor - set the time to current time */ DateTime(); /** * 3 element args constructor - given year, month, and date, * construct a datetime * * @param year the initial year of the datetime * @param month the initial month of the datetime * @param date the initial date of the datetime */ DateTime(t_int32 year, t_int32 month, t_int32 date); /** * 5 element args constructor - given year, month, date, * hrs, and mins, construct a datetime * * @param year the initial year of the datetime * @param month the initial month of the datetime * @param date the initial date of the datetime * @param hrs the initial hours of the datetime * @param min the initial minutes of the datetime */ DateTime(t_int32 year, t_int32 month, t_int32 date, t_int32 hrs, t_int32 min); /** * 6 element args constructor - given year, month, date, * hrs, and mins, construct a datetime * * @param year the initial year of the datetime * @param month the initial month of the datetime * @param date the initial date of the datetime * @param hrs the initial hours of the datetime * @param min the initial minutes of the datetime * @param sec the initial seconds of the datetime */ DateTime(t_int32 year, t_int32 month, t_int32 date, t_int32 hrs, t_int32 min, t_int32 sec); /** * constructor that sets date value to Date arg * * @param d the initial Date value of the datetime */ DateTime(Date d); /** * copy constructor * @param aDateTime the DateTime to copy */ DateTime(DateTime & aDateTime); /** * a constructor that takes a string and converts to datetime. * ASSUMPTION: us is a ISO8601 Date-Time Format * * @param us the UnicodeString to parse, setting Date value * @param timezone the TimeZone to parse in */ DateTime(UnicodeString & us, TimeZone * timezone = ms_TimeZone); ~DateTime(); /*----------------------------- ** GETTERS and SETTERS and ADDERS **---------------------------*/ /** * Returns the value of the Date * * @return the current Date value of this DateTime object */ Date getTime() const; /** * Sets the value of the Date * * @param d the Date arg to set to */ void setTime(Date d); /** * Given a string, sets time to string's value if parseable * NOTE: Currently only accepts ISO8601 strings. * @param us date-time string to set to * @param timezone timezone the date-time should be parsed to * @see parseISO8601 */ void setTimeString(UnicodeString & us, TimeZone * timezone = ms_TimeZone); /** * Set the value of the timezone * * @param t the TimeZone arg to set to */ /*void setTimeZone(TimeZone * t);*/ /** * Returns a field of the calendar * * @param aField the field to return * @param timezone timezone returned field should be relevant to * @return the value of the field * */ t_int32 get(Calendar::EDateFields aField, TimeZone * timezone = ms_TimeZone); /** * @param timezone timezone returned field should be relevant to * @return the year field value */ t_int32 getYear(TimeZone * timezone = ms_TimeZone); /** * @param timezone timezone returned field should be relevant to * @return the month field value */ t_int32 getMonth(TimeZone * timezone = ms_TimeZone); /** * @param timezone timezone returned field should be relevant to * @return the day-of-month field value */ t_int32 getDate(TimeZone * timezone = ms_TimeZone); /** * @param timezone timezone returned field should be relevant to * @return the hour-of-day(24hrs) field value */ t_int32 getHour(TimeZone * timezone = ms_TimeZone); /** * @param timezone timezone returned field should be relevant to * @return the minute field value */ t_int32 getMinute(TimeZone * timezone = ms_TimeZone); /** * @param timezone timezone returned field should be relevant to * @return the second field value */ t_int32 getSecond(TimeZone * timezone = ms_TimeZone); /** * @param timezone timezone returned field should be relevant to * @return the day-of-week-in-month field value */ t_int32 getDayOfWeekInMonth(TimeZone * timezone = ms_TimeZone); /** * Set the day month and year of d2 to the supplied values * * @param iDay the desired day of the month * @param iMonth the desired month of the year * @param iYear the desired year * @return the updated DateTime */ void setDMY(t_int32 iDay, t_int32 iMonth, t_int32 iYear); void setDayOfMonth(t_int32 iDay); /** * Sets the value of a calendar field to an amount * * @param aField the field to set * @param amount the amount of the field */ void set(Calendar::EDateFields, t_int32 value); /** * Adds the an amount to the value of a calendar field * * @param aField the field to add * @param amount the amount of the field */ void add(Calendar::EDateFields, t_int32 amount); /** * adds a duration amount to this datetime * @param d the duration to add */ void add(nsCalDuration d); /** * subtracts a duration amount from this datetime * @param d the duration to subtract */ void subtract(nsCalDuration d); /** * given two datetimes, return the duration length between them. * if end before start, return an invalid duration. */ static nsCalDuration & getDuration(DateTime start, DateTime end, nsCalDuration & out); /** * Clears all fields */ void clear(); /*----------------------------- ** UTILITIES **---------------------------*/ /** * A invalid DateTime has a Date value less than 0. * * @return TRUE if valid, FALSE otherwise. */ t_bool isValid(); /** * Sets this DateTime to the previous day */ void prevDay(); /** * Sets this DateTime to a previous number of days * @param i number of days to go back */ void prevDay(t_int32 i); /** * Sets this DateTime to the next day */ void nextDay(); /** * Sets this DateTime ahead a number of days * @param i number of days to go ahead */ void nextDay(t_int32 i); /** * Sets this DateTime to the prev week */ void prevWeek(); /** * Sets this DateTime to the next week */ void nextWeek(); /* moves by week */ void moveTo(t_int32 i, t_int32 direction, t_bool force); void setByISOWeek(t_int32 week); /** * Sets this DateTime to the previous month */ void prevMonth(); /** * Sets this DateTime to a previous number of months * @param iLim number of months to go back */ void prevMonth(t_int32 iLim); /** * Sets this DateTime to the next month */ void nextMonth(); /** * Sets this DateTime to advance a number of months * @param iLim number of months to advance */ void nextMonth(t_int32 iLim); /**--------------------------------------------------------------------- ** prevDOW ** ** This method is useful in determining the beginning of a calendar ** week. The idea is: you pass in the day of the week the user ** wants as the first day of the week and this routine finds it. ** if the date passed in is already the desired day, the same date ** is returned. Otherwise, it goes backwards until it finds the ** desired day of the week. *** *** @param n back the this date off to the supplied day-of-the-week *** This parameter must be one of Calendar::SUNDAY through *** Calendar::SATURDAY. *** *** @return the number of days backed off *** *** sman@netscape.com ***--------------------------------------------------------------------*/ t_int32 prevDOW(t_int32 n); /* Boolean check methods */ /** * @param dt DateTime to compare with * @return -1 if this DateTime is before, 0 if equal, 1 if afte */ t_int32 compareTo(DateTime &dt); /** * @param d Date to compare with * @return TRUE if this DateTime is before a Date, FALSE otherwise * @deprecated */ t_bool beforeDate(Date d); t_bool beforeDateTime(DateTime dt); t_bool before(DateTime * dt); /** * @param d Date to compare with * @return TRUE if this DateTime is after a Date, FALSE otherwise * @deprecated */ t_bool afterDate(Date d); t_bool afterDateTime(DateTime dt); t_bool after(DateTime * dt); /** * @param d Date to compare with * @return TRUE if this DateTime is equals a Date, FALSE otherwise * @deprecated */ t_bool equalsDate(Date d); t_bool equalsDateTime(DateTime dt); t_bool equals(DateTime * dt); /** * This method returns TRUE if the supplied date is on the same * day, month, and year as this date. * * @param d datetime to compare against * @param timezone timezone that d is in * @return TRUE if day, month and year fields in d and this DateTime match, FALSE otherwise */ t_bool sameDMY(DateTime * d, TimeZone * timezone = ms_TimeZone); /* PRINT methods */ /** * Returns this DateTime to a localized string * * @param timezone timezone to localize to * @return the localized string of the date */ UnicodeString toString(TimeZone * timezone = ms_TimeZone); /** * Returns this DateTime to a the GMT ISO8601 format * * @param timezone timezone to localize to * @return the GMT ISO8601 format of the date */ UnicodeString toISO8601Local(TimeZone * timezone = ms_TimeZone); /** * Returns this DateTime to a the localized ISO8601 format * * @return the localized ISO8601 format of the date */ UnicodeString toISO8601(); /** * Return the Time string in ISO8601 format w/respect to GMT * For example a DateTime equal to 19981225T013000Z would return * the string "013000". * * @return output time string */ UnicodeString toISO8601TimeOnly(); /** * Return the Date string in ISO8601 format w/respect to GMT * For example a DateTime equal to 19981225T013000Z * would return the string "19981225". * * @return output date string */ UnicodeString toISO8601DateOnly(); /** * Return the Time string in ISO8601 format w/respect to timezone argument. * For example a DateTime equal to 19981225T013000Z, and a timezone arg of EST * would return the string "193000" since it is 7:30 PM in Eastern Standard Time. * @param timezone timezone to apply to. */ UnicodeString toISO8601LocalTimeOnly(TimeZone * timezone = ms_TimeZone); /** * Return the Time string in ISO8601 format w/respect to timezone argument. * For example a DateTime equal to 19981225T013000Z, and a timezone arg of EST * would return the string "19981224" since it is Dec 24th in Eastern Standard Time. * @param timezone timezone to apply to. */ UnicodeString toISO8601LocalDateOnly(TimeZone * timezone = ms_TimeZone); /** * Returns a string representing the formatted string of the datetime * given a formatting string. Applies result to the timezone passed in. * For example, if the datetime was 19981225T013000Z and if * pattern was "MM/dd/yy hh:mm:ss a z" and timezone was * EST, the returned string would be "12/24/98 07:30:00 PM EST". * * @param pattern the date-format pattern * @param timezone timezone to apply to * @return the formatted string of this DateTime */ UnicodeString strftime(UnicodeString& pattern, TimeZone * timezone = ms_TimeZone); /** * Returns a string representing the formatted string of the datetime * given a formatting string. Must create new DateFormat object to * pass in locale * NOTE: Slow since creates new SimpleDateFormat * * @param pattern the date-format pattern * @param locale the locale to print in * @param timezone the timezone to format in (default to 0) * @return the formatted string of this DateTime */ UnicodeString strftime(UnicodeString& pattern, Locale & locale, TimeZone * timezone = 0); /** * Sets this DateTime to the last day of the month of s. * Thus if s has a month value of March, then this * DateTime is set to March 31. * * @param s a DateTime */ void findLastDayOfMonth(); /* go to last day of current month */ /** * Sets this DateTime to the last day of the year of s. * Thus if s has a year value of 1998, then this * DateTime is set to Dec 31, 1998. * * @param s a DateTime */ void findLastDayOfYear(); /* go to last day of current year */ /*----------------------------- ** STATIC METHODS **---------------------------*/ /** * Given the day of the week indicator, * return the next day of the week indicator * * @param n the day of the week, for example: Calendar::MONDAY * @return the next day of the week */ static t_int32 getPrevDOW(t_int32 n); /** * Given the day of the week indicator, * return the next day of the week indicator * * @param n the day of the week, for example: Calendar.MONDAY * @return the next day of the week */ static t_int32 getNextDOW(t_int32 n); /** * Returns string of dt. * @param DateTime & dt * * @return static UnicodeString */ static UnicodeString DateToString(DateTime & dt); /** * Given a string, checks to see whether the string is valid * ISO8601 DateTime or Date string. * * A valid ISO8601 DateTime has the following grammar. * [year][month][day]'T'[hour][minute][second] * * In addition, the DateTime may have an optional 'Z' * character at the end to signify UTC time. * * A valid ISO8601 Date has the following grammar. * [year][month][day] * * The year part contains four numbers. * The month part contains two numbers comprising a valid month value [01-12]. * The day part contains two numbers comprising a valid day value [01-31]. * The day part must also match the month and year values (i.e. * cannot have month = 02 and day = 31.) * The hour part contains two numbers comprising a valid hour value [00-23]. * The minute part contains two numbers comprising a valid minute value [00-59]. * The second part contains two numbers comprising a valid second value [00-59]. * * If the string is a valid ISO8601 DateTime or Date string, then this method * will correctly fill in the passed in integer variables with their * appropriate value. For example, if the string was "19971225T123045Z", * the returned values would be iYear = 1997, iMonth = 12, iDay = 25, iHour = 12, * iMinute = 30, iSecond = 45. * @param s string to check if valid * @param iYear returned year value * @param iMonth returned month value * @param iDay returned day value * @param iHour returned hour value * @param iMinute returned minute value * @param iSecond returned second value * * @return TRUE if string is a valid ISO8601 DateTime or Date string, FALSE otherwise */ static t_bool IsParseable(UnicodeString & s, t_int32 & iYear, t_int32 & iMonth, t_int32 & iDay, t_int32 & iHour, t_int32 & iMinute, t_int32 & iSecond); /** * Given a string, checks to see whether the string is valid * ISO8601 DateTime or Date string. * @param s string to check if valid * * @return TRUE if string is a valid ISO8601 DateTime or Date string, FALSE otherwise */ static t_bool IsParseable(UnicodeString & s); /** * Given a string, checks to see whether the string is valid * ISO8601 DateTime string. * @param s string to check if valid * * @return TRUE if string is a valid ISO8601 DateTime, FALSE otherwise */ static t_bool IsParseableDateTime(UnicodeString & s); /** * Given a string, checks to see whether the string is valid * ISO8601 Date string. * @param s string to check if valid * * @return TRUE if string is a valid ISO8601 Date, FALSE otherwise */ static t_bool IsParseableDate(UnicodeString & s); /** * Given a string, checks to see whether the string is valid * ISO8601 UTCOffset string. * @param s string to check if valid * * @return TRUE if string is a valid UTCOffset, FALSE otherwise */ static t_bool IsParseableUTCOffset(UnicodeString & s); /** * Return the string "19980825T112233" from * year = 98, month = 8, day = 25, hour = 11, minute = 22, second = 33 * in sResult. * @param t_int32 iYear * @param t_int32 iMonth * @param t_int32 iDay * @param t_int32 iHour * @param t_int32 iMinute * @param t_int32 iSecond * @param UnicodeString sResult * * @return static UnicodeString */ static UnicodeString & ToISO8601String(t_int32 iYear, t_int32 iMonth, t_int32 iDay, t_int32 iHour, t_int32 iMinute, t_int32 iSecond, UnicodeString & sResult); /** * Given a string, checks to see whether the string is valid * ISO8601 UTCOffset string. * * A valid UTCOffset has the following grammar: * [+/-][hour][minute] * * The first character must be a plus or minus character. * The hour part contains two numbers comprising a hour offset [0-12] * The minute part contains two number comprising a minute offset [0-59] * * If the string is a valid UTCOffset, then the methods * will correctly fill in the argument integers with their * appropriate value. For * @param s string to check if valid * @param t_int32 & iHour * @param t_int32 & iMinute * * @return static t_bool */ static t_bool IsParseableUTCOffset(UnicodeString & s, t_int32 & iHour, t_int32 & iMinute); /* compare method to pass into JulianPtrArray::QuickSort */ static int CompareDateTimes(const void * a, const void * b); /*----------------------------- ** OVERLOADED OPERATORS **---------------------------*/ /** * assignment operator * * @param that DateTime to copy * @return a copy of that DateTime */ const DateTime &operator=(const DateTime & that); /** * equality operator * * @param that DateTime to copy * @return TRUE if equal, FALSE otherwise */ t_bool operator==(const DateTime & that); /** * inequality operator * * @param that DateTime to copy * @return TRUE if NOT equal, FALSE otherwise */ t_bool operator!=(const DateTime & that); /** * greater than operator * * @param that DateTime to copy * @return TRUE if after, FALSE otherwise */ t_bool operator>(const DateTime & that); /** * less than operator * * @param that DateTime to copy * @return TRUE if befor, FALSE otherwise */ t_bool operator<(const DateTime & that); }; #endif /* __DATETIME_H_ */