updates to move to newer gnu-er time
[feisty_meow.git] / nucleus / library / timely / earth_time.h
1 #ifndef EARTH_TIME_GROUP
2 #define EARTH_TIME_GROUP
3
4 /*
5   Name   : earth_time
6   Author : Chris Koeritz
7
8   Copyright (c) 1999-$now By Author.  This program is free software; you can
9   redistribute it and/or modify it under the terms of the GNU General Public
10   License as published by the Free Software Foundation; either version 2 of
11   the License or (at your option) any later version.  This is online at:
12       http://www.fsf.org/copyleft/gpl.html
13   Please send any updates to: fred@gruntose.com
14 */
15
16 #include <basis/astring.h>
17 #include <basis/byte_array.h>
18 #include <basis/contracts.h>
19 //#include <basis/definitions.h>
20 #include <structures/object_packers.h>
21
22 ///#include <time.h>
23
24 //! A set of methods for rendering calendrical and clock times.
25 /*!
26   It is based on the Gregorian calendar currently in use by the USA and other
27   countries.
28 */
29 namespace timely {
30
31   typedef basis::signed_long time_number;
32
33   enum days { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY };
34     //!< The names of the days of the week.
35
36   days day_now();  //!< Returns the current local day.
37
38   const char *day_name(days to_name);
39     //!< Returns the name of the day "to_name".
40
41   enum months { JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST,
42       SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER };
43     //!< The names of the months in our calendar.
44
45   months month_now();  //!< returns the local month.
46
47   const char *month_name(months to_name);
48     //!< Returns the name of the month "to_name".
49   const char *short_month_name(months to_name);
50     //!< Returns a shorter, constant-length (3 characters) month name.
51
52   extern const time_number days_in_month[12];
53     //!< The number of days in each month in the standard year.
54   extern const time_number leap_days_in_month[12];
55     //!< The number of days in each month in a leap year.
56
57   extern const time_number julian_days_in_month[12];
58     //!< Number of days in each month based on the julian calendar.
59   extern const time_number julian_leap_days_in_month[12];
60     //!< Number of days in each month of a leap year in the julian calendar.
61
62   const time_number SECONDS_IN_MINUTE = 60;  //!< Number of seconds in one minute.
63   const time_number MINUTES_IN_HOUR = 60;  //!< Number of minutes in an hour.
64   const time_number SECONDS_IN_HOUR = 3600;  //!< Number of seconds in an hour.
65   const time_number HOURS_IN_DAY = 24;  //!< Number of hours in a day.
66   const time_number MINUTES_IN_DAY = 1440;  //!< Number of minutes in a day.
67   const time_number SECONDS_IN_DAY = 86400;  //!< Number of seconds in a day.
68   const time_number DAYS_IN_YEAR = 365;  //!< Number of days in a standard year.
69   const time_number LEAP_DAYS_IN_YEAR = 366;  //!< Number of days in a leap year.
70   const double APPROX_DAYS_IN_YEAR = 365.2424;
71     //!< A more accurate measure of the number of days in a year.
72     /*!< This is the more accurate mean length of time in 24 hour days between
73     vernal equinoxes.  it's about 11 minutes shy of 365.25 days. */
74
75   //! An enumeration of time zones, both relative and absolute.
76   enum time_zones {
77     LOCAL_ZONE,      //!< The time zone this computer is configured to report.
78     GREENWICH_ZONE   //!< The time zone of Greenwich Mean Time.
79   };
80
81   // now some structures for representing time...
82
83   //! A specific point in time as represented by a 24 hour clock.
84   class clock_time : public virtual basis::packable
85   {
86   public:
87     time_number hour;  //!< The hour represented in military time: 0 through 23.
88     time_number minute;  //!< The number of minutes after the hour.
89     time_number second;  //!< The number of seconds after the current minute.
90     time_number millisecond;  //!< The number of milliseconds elapsed in this second.
91     time_number microsecond;  //!< Number of microseconds elapsed in this millisecond.
92
93     //! Constructs a clock_time object given all the parts.
94     clock_time(time_number h = 0, time_number m = 0, time_number s = 0, time_number ms = 0, time_number us = 0)
95              : hour(h), minute(m), second(s), millisecond(ms),
96                microsecond(us) {}
97     ~clock_time() {}
98
99     int packed_size() const { return 5 * structures::PACKED_SIZE_INT32; }
100
101     virtual void pack(basis::byte_array &packed_form) const;
102       //!< Packs a clock time into an array of bytes.
103     virtual bool unpack(basis::byte_array &packed_form);
104       //!< Unpacks a clock time from an array of bytes.
105
106     bool operator < (const clock_time &to_compare) const;
107       //!< Returns true if this clock_time is earlier than "to_compare"
108     bool operator == (const clock_time &to_compare) const;
109       //!< Returns true if this clock_time is equal to "to_compare"
110
111     //! An enumeration of time formatting modes used when printing the time.
112     enum time_formats {
113       MERIDIAN = 0x1,  //!< default: uses 12 hour with AM/PM and no seconds.
114       MILITARY = 0x2,  //!< use military 24 hour time.
115       NO_AM_PM = 0x4,  //!< use 12 hour time but don't include AM/PM.
116       SECONDS = 0x8,   //!< include the number of seconds as a third field.
117       MILLISECONDS = 0x10  //!< milliseconds are fourth field (after secs).
118     };
119
120     basis::astring text_form(int how = MERIDIAN) const;
121       //!< Prints the clock_time according to "how".
122       /*!< "how" is a combination of time_formats. */
123     void text_form(basis::astring &to_stuff, int how = MERIDIAN) const;
124       //!< Prints the time into "to_stuff" given "how".
125       /*!< note that "to_stuff" will be appended to; the existing contents
126       are retained. */
127
128     static time_number normalize(clock_time &to_fix);
129       // ensures that the units in each field are in the proper range by
130       // promoting them upwards.  if the clock_time goes above the maximum hour,
131       // then it rolls around.  zero is returned for no rollover or a positive
132       // integer is returned for the number of rollovers that occurred.  if
133       // there are any negative fields, they are rolled backwards.
134       // the returned rollovers are measured in days.
135   };
136
137   //! An object that represents a particular day in a year.
138   class day_in_year : public virtual basis::packable
139   {
140   public:
141     months month;  //!< The current month.
142     time_number day_in_month;  //!< The day number within the month (starting at one).
143     days day_of_week;  //!< The day of the week.
144     time_number day_of_year;  //!< Numerical day, where January 1st is equal to zero.
145
146     int packed_size() const { return 4 * structures::PACKED_SIZE_INT64; }
147
148     //! Constructs a representation of the day specified.
149     day_in_year(months m = JANUARY, time_number dim = 1, days dow = SUNDAY,
150             time_number day_o_year = 1) : month(m), day_in_month(dim),
151             day_of_week(dow), day_of_year(day_o_year) {}
152
153     virtual void pack(basis::byte_array &packed_form) const;
154       //!< Packs a day object into an array of bytes.
155     virtual bool unpack(basis::byte_array &packed_form);
156       //!< Unpacks a day object from an array of bytes.
157
158     bool operator < (const day_in_year &to_compare) const;
159       //!< Returns true if this day is earlier than "to_compare"
160       /*!< Note that this only compares the month and day in the month. */
161     bool operator == (const day_in_year &to_compare) const;
162       //!< Returns true if this day is equal to "to_compare"
163       /*!< Note that this only compares the month and day in the month. */
164
165     //! An enumeration of ways to print out the current date.
166     enum date_formats {
167       // note: these classes may need to be revised in the year 9999.
168       SHORT_MONTH = 0x1,    //!< default: three letter month.
169       LONG_MONTH = 0x2,     //!< uses full month name.
170       INCLUDE_DAY = 0x4     //!< adds the name of the day.
171     };
172
173     basis::astring text_form(int how = SHORT_MONTH) const;
174       //!< Prints the day according to "how".
175     void text_form(basis::astring &to_stuff, int how = SHORT_MONTH) const;
176       //!< Prints the day according to "how" and stores it in "to_stuff".
177
178     static time_number normalize(day_in_year &to_fix, bool leap_year = false);
179       //!< normalizes the day as needed and returns the adjustment in years.
180       /*!< note that this only adjusts the day_in_month and month members
181       currently.  the other counters are not changed. */
182   };
183
184   //! An object that represents a particular point in time.
185   /*! It contains both a time of day and the day in the year. */
186   class time_locus : public clock_time, public day_in_year,
187       public virtual basis::hoople_standard
188   {
189   public:
190     time_number year;  //!< The year, using the gregorian calendar.
191
192     time_locus() : clock_time(), day_in_year(), year() {}
193
194     DEFINE_CLASS_NAME("time_locus");
195
196     //! Constructs a location in time given its components.
197     time_locus(const clock_time &ct, const day_in_year &ytd, time_number year_in)
198             : clock_time(ct), day_in_year(ytd), year(year_in) {}
199
200     int packed_size() const { return clock_time::packed_size()
201             + day_in_year::packed_size() + structures::PACKED_SIZE_INT32; }
202
203     virtual void pack(basis::byte_array &packed_form) const;
204       //!< Packs a time_locus object into an array of bytes.
205     virtual bool unpack(basis::byte_array &packed_form);
206       //!< Unpacks a time_locus object from an array of bytes.
207
208     // these implement the orderable and equalizable interfaces.
209     virtual bool equal_to(const basis::equalizable &s2) const;
210     virtual bool less_than(const basis::orderable &s2) const;
211 //old    bool operator < (const time_locus &to_compare) const;
212       //!< Returns true if this time_locus is earlier than "to_compare"
213 //old    bool operator == (const time_locus &to_compare) const;
214       //!< Returns true if this time_locus is equal to "to_compare"
215
216     //! Enumerates the ways to show the year.
217     enum locus_formats {
218       LONG_YEAR = 0x1,  //!< default: full four digit year (problems in 9999).
219       SHORT_YEAR = 0x2  //!< use only last two digits of year.  ugh--Y2K danger.
220     };
221
222     // fulfills obligation for text_formable.
223     virtual void text_form(basis::base_string &state_fill) const {
224       state_fill.assign(text_form_long(clock_time::MERIDIAN, day_in_year::SHORT_MONTH, LONG_YEAR));
225     }
226
227     basis::astring text_form_long(int t = clock_time::MERIDIAN,
228             int d = day_in_year::SHORT_MONTH, int y = LONG_YEAR) const;
229       //! Prints out the time_locus given the way to print each component.
230       /*< "t" is a combination of time_formats, "d" is a combination of
231       date_formats and "y" is a combination of locus_formats. */
232     void text_form_long(basis::astring &to_stuff, int t = clock_time::MERIDIAN,
233             int d = day_in_year::SHORT_MONTH, int y = LONG_YEAR) const;
234       //! Same as text_form() above, but stores into "to_stuff".
235
236     static time_number normalize(time_locus &to_fix);
237       //!< normalizes the time_locus for its clock time and date.
238 //hmmm: what are rollovers measured in?
239   };
240
241   time_number year_now();  //!< what year is it?
242   clock_time time_now();  //!< what time is it?
243   day_in_year date_now();  //!< what day on the calendar is it?
244   time_locus now();  //!< returns our current locus in the time continuum.
245   time_locus greenwich_now();  //!< returns Greenwich Mean Time (their now).
246 } // namespace.
247
248 #endif
249