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