1 /*
2  * Copyright 2006-2008 The FLWOR Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 #ifndef ZORBA_DATETIME_H
18 #define ZORBA_DATETIME_H
19 
20 #include <iostream>
21 
22 #include <zorba/config.h>
23 #include "zorbatypes/timezone.h"
24 #include "zorbatypes/duration.h"
25 
26 #include "util/ascii_util.h"
27 
28 
29 namespace zorba
30 {
31 
32 class DateTime;
33 
34 
35 namespace serialization
36 {
37   class Archiver;
38   void operator&(Archiver& ar, DateTime& obj);
39 }
40 
41 
42 
43 class InvalidTimezoneException : public std::exception
44 {
45 };
46 
47 
48 class DateTime
49 {
50   friend void serialization::operator&(serialization::Archiver& ar, DateTime& obj);
51 
52 public:
53 
54   /** Available facets for the DateTime class */
55   typedef enum
56   {
57     DATETIME_FACET = 0,
58     DATE_FACET = 1,
59     TIME_FACET = 2,
60     GYEARMONTH_FACET = 3,
61     GYEAR_FACET = 4,
62     GMONTH_FACET = 5,
63     GMONTHDAY_FACET = 6,
64     GDAY_FACET = 7
65   } FACET_TYPE;
66 
67   // Only year may be negative, all other must be positive
68   // The year gives the sign of DateTime, Date, etc
69 
70   typedef enum
71   {
72     YEAR_DATA = 0,
73     MONTH_DATA = 1,
74     DAY_DATA = 2,
75     HOUR_DATA = 3,
76     MINUTE_DATA = 4,
77     SECONDS_DATA = 5,
78     FRACSECONDS_DATA = 6
79   } DATA_TYPE;
80 
81 
82   static const int FACET_MEMBERS[8][8];
83 
84   // fractional seconds have 6 digits. 0.1 seconds are represented as 100000,
85   // 0.01 seconds as 10000, etc.
86   static const int FRAC_SECONDS_UPPER_LIMIT; // = 1000000, maximum 6 digits
87 
88 protected:
89   FACET_TYPE facet;
90 
91   long       data[7];
92 
93   TimeZone   the_time_zone;
94 
95 public:
96   /**
97    *  Returns 0 on success
98    *  Returns 2 if both the Date and the Time have a timezone, and they differ (FORG0008)
99    */
100   static int createDateTime(
101         const DateTime* date,
102         const DateTime* time,
103         DateTime& result);
104 
105   /**
106    *  The function will use the absolute values of all int parameters except
107    *  years. No TimeZone.
108    *  Returns 0 on success
109    */
110   static int createDateTime(
111         int years,
112         int months,
113         int days,
114         int hours,
115         int minutes,
116         int seconds,
117         int fractional_seconds,
118         DateTime& dt);
119 
120   /**
121    *  The function will use the absolute values of all int parameters except
122    *  years. TimeZone may be NULL
123    *  Returns 0 on success
124    */
125   static int createDateTime(
126         int years,
127         int months,
128         int days,
129         int hours,
130         int minutes,
131         double seconds,
132         const TimeZone* tz,
133         DateTime& dt);
134 
135   /**
136    *  The function will use the absolute values of all int parameters except
137    *  years. TimeZone may be NULL
138    *  Returns 0 on success
139    */
140   static int createDateTime(
141         int years,
142         int months,
143         int days,
144         int hours,
145         int minutes,
146         int seconds,
147         int fractional_seconds,
148         const TimeZone* tz,
149         DateTime& dt);
150 
151   /**
152    *  The function will use the absolute values of all int parameters except years.
153    *  TimeZone may be NULL
154    *  Returns 0 on success
155    */
156   static int createDate(
157         int years,
158         int months,
159         int days,
160         const TimeZone* tz,
161         DateTime& dt);
162 
163   /**
164    *  The function will use the absolute values of all int parameters. TimeZone
165    *  is a reference
166    *  Returns 0 on success
167    */
168   static int createTime(
169         int hours,
170         int minutes,
171         double seconds,
172         const TimeZone* tz,
173         DateTime& dt);
174 
175   /**
176    *  The function will use the absolute value of the months parameter.
177    *  Returns 0 on success
178    */
179   static int createGYearMonth(int years, int months, DateTime& dt);
180 
181   /**
182    *  Returns 0 on success
183    */
184   static int createGYear(int years, DateTime& dt);
185 
186   /**
187    *  The function will use the absolute values of all int parameters.
188    *  Returns 0 on success
189    */
190   static int createGMonth(int months, DateTime& dt);
191 
192   /**
193    *  The function will use the absolute values of all int parameters.
194    *  Returns 0 on success
195    */
196   static int createGMonthDay(int months, int days, DateTime& dt);
197 
198   /**
199    *  The function will use the absolute values of all int parameters.
200    *  Returns 0 on success
201    */
202   static int createGDay(int days, DateTime& dt);
203 
204   static int getLocalTime(DateTime& dt);
205 
206   /**
207    *  Returns 0 on success
208    */
209   static int parseDateTime(const char* str, ascii::size_type strlen, DateTime& dt);
210 
211   /**
212    *  Returns 0 on success
213    */
214   static int parseDate(const char* str, ascii::size_type strlen, DateTime& dt);
215 
216   /**
217    *  Returns 0 on success
218    */
219   static int parseTime(const char* str, ascii::size_type strlen, DateTime& dt);
220 
221   /**
222    *  Returns 0 on success
223    */
224   static int parseGYearMonth(const char* str, ascii::size_type strlen, DateTime& dt);
225 
226   /**
227    *  Returns 0 on success
228    */
229   static int parseGYear(const char* str, ascii::size_type strlen, DateTime& dt);
230 
231   /**
232    *  Returns 0 on success
233    */
234   static int parseGMonth(const char* str, ascii::size_type strlen, DateTime& dt);
235 
236   /**
237    *  Returns 0 on success
238    */
239   static int parseGMonthDay(const char* str, ascii::size_type strlen, DateTime& dt);
240 
241   /**
242    *  Returns 0 on success
243    */
244   static int parseGDay(const char* str, ascii::size_type strlen, DateTime& dt);
245 
246   static int getDayOfWeek(int year, int month, int day);
247 
248   static int getDayOfYear(int year, int month, int day);
249 
250   static int getWeekInYear(int year, int month, int day);
251 
252   static int getWeekInMonth(int year, int month, int day);
253 
254   static bool isLeapYear(int year);
255 
256 protected:
257   static int parse_date(
258         const char* str,
259         ascii::size_type strlen,
260         ascii::size_type& position,
261         long& year,
262         long& month,
263         long& day);
264 
265   static int parse_time(
266         const char* str,
267         ascii::size_type strlen,
268         ascii::size_type& position,
269         long& hour,
270         long& minute,
271         long& seconds,
272         long& frac_seconds);
273 
274 public:
275   DateTime();
276 
~DateTime()277   virtual ~DateTime() { };
278 
279   void init();
280 
281   DateTime& operator=(const DateTime* dt);
282 
283   /**
284    *  Creates a new DateTime object from the given one, adjusting it to the newly
285    *  given facet. Useful for casting. Will always return 0.
286    */
287   int createWithNewFacet(FACET_TYPE new_facet, DateTime& dt) const;
288 
289   zstring toString() const;
290 
291   DateTime* getDate() const;
292 
293   DateTime* getTime() const;
294 
295   int getYear() const;
296 
297   int getMonth() const;
298 
299   int getDay() const;
300 
301   int getHours() const;
302 
303   int getMinutes() const;
304 
305   xs_decimal getSeconds() const;
306 
307   int getIntSeconds() const;
308 
309   int getFractionalSeconds() const;
310 
311   TimeZone getTimezone() const;
312 
313   /**
314    *  Returns -1 if the DateTime is less than the given DateTime
315    *  Returns 0 if the DateTimes are equal
316    *  Returns 1 if the DateTime is greater than the given DateTime
317    *
318    *  Throws InvalidTimezoneException if the given timezone is not valid.
319    */
320   int compare(const DateTime* dt, long timezone_seconds) const;
321 
322   uint32_t hash(int implicit_timezone_seconds) const;
323 
324   DateTime* addDuration(const Duration& d, bool adjust_facet = true) const;
325 
326   DateTime* subtractDuration(const Duration& d, bool adjust_facet = true) const;
327 
328   /**
329    *  Throws InvalidTimezoneException if the given timezone is not valid.
330    */
331   Duration* subtractDateTime(const DateTime* dt, int implicit_timezone_seconds) const;
332 
333   /**
334    *  Throws InvalidTimezoneException if the given timezone is not valid.
335    */
336   DateTime* normalizeTimeZone(int tz_seconds) const;
337 
338   /**
339    *  Throws InvalidTimezoneException if the given timezone is not valid.
340    */
341   DateTime* adjustToTimeZone(int tz_seconds) const;
342 
343   /**
344    *  Throws InvalidTimezoneException if the given timezone is not valid.
345    */
346   DateTime* adjustToTimeZone(const Duration* db_t) const;
347 
getFacet()348   FACET_TYPE getFacet() const { return facet; };
349 
350   /**
351    *  For a given Date or DateTime, it will return the respective day of the week,
352    *  with the index being 0 based, with 0 being Sunday, 1 Monday, etc. If the give
353    *  DateTime does not have a Date or DateTime facet, the function will return -1.
354    */
355   int getDayOfWeek() const;
356   int getDayOfYear() const;
357   int getWeekInYear() const;
358   int getWeekInMonth() const;
359   bool isLeapYear() const;
360 
361 protected:
362   Duration* toDayTimeDuration() const;
363 
364   void adjustToFacet();
365 
366   void setFacet(FACET_TYPE a_facet);
367 };
368 
369 inline std::ostream& operator<<( std::ostream &o, DateTime const &dt ) {
370   return o << dt.toString();
371 }
372 
373 } // namespace zorba
374 #endif /* ZORBA_DATETIME_H */
375 /*
376  * Local variables:
377  * mode: c++
378  * End:
379  */
380 /* vim:set et sw=2 ts=2: */
381