Updated license
[anna.git] / include / anna / dbms / Date.hpp
1 // ANNA - Anna is Not Nothingness Anymore
2 //
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
4 //
5 // https://bitbucket.org/testillano/anna
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
9 // are met:
10 //
11 //     * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 //     * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
16 // distribution.
17 //     * Neither the name of Google Inc. nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 //
33 // Authors: eduardo.ramos.testillano@gmail.com
34 //          cisco.tierra@gmail.com
35
36
37 #ifndef anna_dbms_Date_hpp
38 #define anna_dbms_Date_hpp
39
40 #include <time.h>
41
42 #include <anna/config/defines.hpp>
43 #include <anna/core/RuntimeException.hpp>
44
45 #include <anna/dbms/Data.hpp>
46
47 namespace anna {
48
49 namespace dbms {
50
51 /**
52    Tipo de datos que permite trabajar con el tipo de dato 'Date' de un gestor de base de
53    datos generico.
54
55    Dependiendo el gestor de base de datos usado el tipo \em date puede contener informacion que incluya
56    la hora del día, en Oracle (tm) la incluye, mientras que en mysql, por ejemplo, no la incluye.
57
58    Internamente trabaja con una estructura de tipo 'tm' que habitualmente tendrá los campos:
59    \code
60    struct tm {
61      int tm_sec;                   // Seconds.     [0-60] (1 leap second)
62      int tm_min;                   // Minutes.     [0-59]
63      int tm_hour;                  // Hours.       [0-23]
64      int tm_mday;                  // Day.         [1-31]
65      int tm_mon;                   // Month.       [0-11]
66      int tm_year;                  // Year - 1900.
67      int tm_wday;                  // Day of week. [0-6]
68      int tm_yday;                  // Days in year.[0-365]
69      int tm_isdst;                 // DST.         [-1/0/1]
70    };
71    \endcode
72 */
73 class Date : public Data {
74 public:
75   /**
76    * Espacio maximo reservado para representar lo datos de una fecha sobre una cadena.
77    */
78   static const int MaxDateSize = 48;
79
80   /**
81      Constructor.
82      \param isNulleable Indica si el dato puede tomar valores nulos.
83      \param format Formato usado para interpretar los datos de esta fecha, en los metodos Date::getCStringValue y
84      Date::setValue (const char*) y Date::setValue (const std::string&). Sigue la especificacion:
85
86      \code
87       %a     Replaced by the localeâs abbreviated weekday name. [ tm_wday]
88
89       %A     Replaced by the localeâs full weekday name. [ tm_wday]
90
91       %b     Replaced by the localeâs abbreviated month name. [ tm_mon]
92
93       %B     Replaced by the localeâs full month name. [ tm_mon]
94
95       %c     Replaced  by  the  localeâs  appropriate date and time representation.  (See the Base Definitions volume of
96              IEEE Std 1003.1-2001, <time.h>.)
97
98       %C     Replaced by the year divided by 100 and truncated to an integer, as a decimal number [00,99]. [ tm_year]
99
100       %d     Replaced by the day of the month as a decimal number [01,31]. [ tm_mday]
101
102       %D     Equivalent to %m / %d / %y . [ tm_mon, tm_mday, tm_year]
103
104       %e     Replaced by the day of the month as a decimal number [1,31]; a single digit  is  preceded  by  a  space.  [
105              tm_mday]
106
107       %F     Equivalent to %Y - %m - %d (the ISO 8601:2000 standard date format). [ tm_year, tm_mon, tm_mday]
108
109       %g     Replaced  by  the  last 2 digits of the week-based year (see below) as a decimal number [00,99]. [ tm_year,
110              tm_wday, tm_yday]
111
112       %G     Replaced by the week-based year (see below) as a decimal number (for example, 1977).  [  tm_year,  tm_wday,
113              tm_yday]
114
115       %h     Equivalent to %b . [ tm_mon]
116
117       %H     Replaced by the hour (24-hour clock) as a decimal number [00,23].  [ tm_hour]
118
119       %I     Replaced by the hour (12-hour clock) as a decimal number [01,12].  [ tm_hour]
120
121       %j     Replaced by the day of the year as a decimal number [001,366]. [ tm_yday]
122
123       %m     Replaced by the month as a decimal number [01,12]. [ tm_mon]
124
125       %M     Replaced by the minute as a decimal number [00,59]. [ tm_min]
126
127       %n     Replaced by a <newline>.
128
129       %p     Replaced by the localeâs equivalent of either a.m. or p.m. [ tm_hour]
130
131       %r     Replaced  by the time in a.m. and p.m. notation;    in the POSIX locale this shall be equivalent to %I : %M
132              : %S %p .  [ tm_hour, tm_min, tm_sec]
133
134       %R     Replaced by the time in 24-hour notation ( %H : %M ).  [ tm_hour, tm_min]
135
136       %S     Replaced by the second as a decimal number [00,60]. [ tm_sec]
137
138       %t     Replaced by a <tab>.
139
140       %T     Replaced by the time ( %H : %M : %S ). [ tm_hour, tm_min, tm_sec]
141
142       %u     Replaced by the weekday as a decimal number [1,7], with 1 representing Monday. [ tm_wday]
143
144       %U     Replaced by the week number of the year as a decimal number [00,53].  The first Sunday of  January  is  the
145              first day of week 1; days in the new year before this are in week 0. [ tm_year, tm_wday, tm_yday]
146
147       %V     Replaced  by the week number of the year (Monday as the first day of the week) as a decimal number [01,53].
148              If the week containing 1 January has four or more days in the new year, then it is considered week 1.  Oth-
149              erwise,  it  is  the  last week of the previous year, and the next week is week 1. Both January 4th and the
150              first Thursday of January are always in week 1. [ tm_year, tm_wday, tm_yday]
151
152       %w     Replaced by the weekday as a decimal number [0,6], with 0 representing Sunday. [ tm_wday]
153
154       %W     Replaced by the week number of the year as a decimal number [00,53].  The first Monday of  January  is  the
155              first day of week 1; days in the new year before this are in week 0. [ tm_year, tm_wday, tm_yday]
156
157       %x     Replaced   by   the  localeâs  appropriate  date  representation.  (See  the  Base  Definitions  volume  of
158              IEEE Std 1003.1-2001, <time.h>.)
159
160       %X     Replaced  by  the  localeâs  appropriate  time  representation.  (See  the  Base  Definitions   volume   of
161              IEEE Std 1003.1-2001, <time.h>.)
162
163       %y     Replaced by the last two digits of the year as a decimal number [00,99].  [ tm_year]
164
165       %Y     Replaced by the year as a decimal number (for example, 1997). [ tm_year]
166
167       %z     Replaced  by  the offset from UTC in the ISO 8601:2000 standard format ( +hhmm or -hhmm ), or by no charac-
168              ters if no timezone is determinable. For example, "-0430" means 4 hours 30  minutes  behind  UTC  (west  of
169              Greenwich).    If tm_isdst is zero, the standard time offset is used. If tm_isdst is greater than zero, the
170              daylight savings time offset is used. If tm_isdst is negative, no characters are returned.  [ tm_isdst]
171
172       %Z     Replaced by the timezone name or abbreviation, or  by  no  bytes  if  no  timezone  information  exists.  [
173              tm_isdst]
174
175       %%     Replaced by % .
176      \endcode
177
178      Para obtener más informacion sobre la espeficacion de formato \em man \em strftime (p.e.).
179   */
180   explicit Date(const bool isNulleable = false, const char* format = NULL) ;
181
182   /**
183      Constructor copia.
184      \param other Instancia de la que copiar.
185   */
186   Date(const Date& other);
187
188   /**
189      Destructor.
190   */
191   virtual ~Date();
192
193   /**
194      Devuelve el contenido de esta fecha.
195      \return El contenido de esta fecha.
196      \warning Si el metodo Data::isNull devolvio \em true el contenido de la estructura no esta definido.
197   */
198   const tm& getValue() const throw() { return a_value; }
199
200   /**
201      Devuelve el contenido de esta fecha.
202      \return El contenido de esta fecha.
203      \warning Si el metodo Data::isNull devolvio \em true el contenido de la estructura no esta definido.
204   */
205   tm& getValue() throw() { return a_value; }
206
207   /**
208    * Interpreta el contenido de la fecha y lo transfiere al buffer.
209    * \return El buffer que contiene esta fecha interpretada con el formato indicado en el contructor.
210    *  \warning El resultado sera NULL en caso de no poder interpretar correctamente la fecha.
211    */
212   virtual const char* getCStringValue() const throw();
213
214   /**
215    * Interpreta el contenido de esta fecha como el numero de segundos transcurridos desde el 1 de Enero de 1970.
216    * Si el contenido de la columna sociada es nulo este metodo devolvera 0. Si la conversion a segundos no puede
217    * ser realizada devolvera -1.
218    * \return Interpreta el contenido de esta fecha como el numero de segundos transcurridos desde el 1 de Enero de 1970.
219    * Si el contenido de la columna sociada es nulo este metodo devolvera 0. Si la conversion a
220    * segundos no puede ser realizada devolvera -1.
221    */
222   Second getSecondValue() const throw() { return Second((Data::isNull() == true) ? 0 : mktime(&const_cast <Date*>(this)->a_value)); }
223
224   /**
225    * Devuelve el formato indicado en el constructor de la clase.
226    * \return El formato indicado en el constructor de la clase.
227    */
228   const char* getFormat() const throw() { return a_format; }
229
230   /**
231    * Devuelve el año contenido por esta fecha.
232    * \return El año contenido por esta fecha.
233    */
234   int getYear() const throw() { return a_value.tm_year + 1900; }
235
236   /**
237    * Devuelve el mes contenido por esta fecha.
238    * \return El mes contenido por esta fecha.
239    */
240   int getMonth() const throw() { return a_value.tm_mon + 1; }
241
242   /**
243    * Devuelve el dia del mes contenido por esta fecha.
244    * \return El dia del mes contenido por esta fecha.
245    */
246   int getDay() const throw() { return a_value.tm_mday; }
247
248   /**
249    * Devuelve la hora del dia contenida en la fecha.
250    * \return La hora del dia contenida en la fecha.
251    * \warning Verifique que el tipo 'Date' de su RDBMS es capaz de contener horas, minutos y segundos.
252    */
253   int getHour() const throw() { return a_value.tm_hour; }
254
255   /**
256    * Devuelve el minuto de la hora contenida en la fecha.
257    * \return El minuto de la hora contenida en la fecha.
258    * \warning Verifique que el tipo 'Date' de su RDBMS es capaz de contener horas, minutos y segundos.
259    */
260   int getMinute() const throw() { return a_value.tm_min; }
261
262   /**
263    * Devuelve el segundo de la hora contenida en la fecha.
264    * \return El segundo de la hora contenida en la fecha.
265    * \warning Verifique que el tipo 'Date' de su RDBMS es capaz de contener horas, minutos y segundos.
266    */
267   int getSecond() const throw() { return a_value.tm_sec; }
268
269   /**
270    * Establece el año de esta fecha
271    * \param year Año de la fecha. Debe ser mayor de 1900.
272    */
273   void setYear(const int year) throw(RuntimeException) { set("Year", a_value.tm_year, year - 1900, 0, -1); }
274
275   /**
276    * Establece mes de esta fecha.
277    * \param month Mes de la fecha. Debe estar comprendido entre 1 y 12.
278    */
279   void setMonth(const int month) throw(RuntimeException) { set("Month", a_value.tm_mon, month - 1, 0, 11); }
280
281   /**
282    * Establece el dia del mes de esta fecha.
283    * \param day Dia del mes. Debe estar comprendido entre 1 y 31.
284    */
285   void setDay(const int day) throw(RuntimeException) { set("Day", a_value.tm_mday, day, 1, 31); }
286
287   /**
288    * Establece la hora de esta fecha.
289    * \param hour Hora del dia. Debe estar comprendida entre 0 y 23.
290    * \warning Verifique que el tipo 'Date' de su RDBMS es capaz de contener horas, minutos y segundos.
291    */
292   void setHour(const int hour) throw(RuntimeException) { set("Hour", a_value.tm_hour, hour, 0, 23); }
293
294   /**
295    * Establece el minuto de esta fecha.
296    * \param minute Minuto de la hora del dia. Debe estar comprendida entre 0 y 59.
297    * \warning Verifique que el tipo 'Date' de su RDBMS es capaz de contener horas, minutos y segundos.
298    */
299   void setMinute(const int minute) throw(RuntimeException) { set("Minute", a_value.tm_min, minute, 0, 59); }
300
301   /**
302    * Establece el segundo de esta fecha.
303    * \param second Segungo de la hora del dia. Debe estar comprendida entre 0 y 60.
304    * \warning Verifique que el tipo 'Date' de su RDBMS es capaz de contener horas, minutos y segundos.
305    */
306   void setSecond(const int second) throw(RuntimeException) { set("Second", a_value.tm_sec, second, 0, 60); }
307
308   /**
309      Interpreta la cadena recibida segun el formato indicado en el constructor y la asigna a esta instancia, pero requiere que al
310      invocar al constructor de esta fecha se indique el formato usado para traducir.
311      \param str Cadena de la que copiar.
312   */
313   void setValue(const char* str) throw(RuntimeException);
314
315   /**
316      Interpreta la cadena recibida segun el formato indicado en el constructor y la asigna a esta instancia, pero requiere que al
317      invocar al constructor de esta fecha se indique el formato usado para traducir.
318      \param str Cadena de la que copiar.
319   */
320   void setValue(const std::string& str) throw(RuntimeException) { setValue(str.c_str()); }
321
322   /**
323    * Establece esta fecha con los segundos transcurridos desde el 1/1/1970.
324    * \param second Numeros de segundos transcurridos desde el 1 de Enero de 1970.
325    * \see anna::functions::second
326    */
327   void setValue(const Second &second) throw(RuntimeException);
328
329   /**
330      Operador de copia.
331      \param date Fecha de la que copiar.
332      \return La instancia de esta fecha.
333      \warning Solo copia el contenido de la fecha recibida, no cambia el formato de interpretacion de la fecha origen.
334   */
335   Date& operator = (const Date& date) throw(RuntimeException);
336
337   /**
338      Devuelve una cadena con la informacion referente a esta instancia.
339      \return Una cadena con la informacion referente a esta instancia.
340   */
341   virtual std::string asString() const throw();
342
343 protected:
344   char* a_format;
345   tm a_value;
346   char a_buffer  [MaxDateSize + 1];
347
348   /**
349    * Constructor invocado desde el constructor de TimeStamp.
350      \param type Sera Data::Type::TimeStamp.
351      \param isNulleable Indica si el dato puede tomar valores nulos.
352      \param format Formato usado para representar los datos de esta fecha.
353    */
354   explicit Date(const Type::_v type, const bool isNulleable, const char* format);
355
356 private:
357   void set(const char* what, int& variable, const int value, const int min, const int max) throw(RuntimeException);
358   void do_clear() throw() { anna_memset(&a_value, 0, sizeof(a_value)); }
359 };
360
361 }
362 }
363
364 #endif
365