GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
oct-time.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1999-2013 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 #include <limits>
28 
29 #include <ctime>
30 
31 #include <sys/time.h>
32 #include <sys/types.h>
33 #include <unistd.h>
34 
35 #include "strftime.h"
36 
37 #include "lo-error.h"
38 #include "lo-math.h"
39 #include "lo-utils.h"
40 #include "oct-locbuf.h"
41 #include "oct-time.h"
42 
44  : ot_unix_time (), ot_usec ()
45 {
46  struct tm t;
47 
48  t.tm_sec = tm.sec ();
49  t.tm_min = tm.min ();
50  t.tm_hour = tm.hour ();
51  t.tm_mday = tm.mday ();
52  t.tm_mon = tm.mon ();
53  t.tm_year = tm.year ();
54  t.tm_wday = tm.wday ();
55  t.tm_yday = tm.yday ();
56  t.tm_isdst = tm.isdst ();
57 
58 #if defined (HAVE_STRUCT_TM_GMTOFF)
59  t.tm_gmtoff = tm.gmtoff ();
60 #endif
61 
62 #if defined (HAVE_STRUCT_TM_TM_ZONE)
63  std::string s = tm.zone ();
64  char *ps = strsave (s.c_str ());
65  t.tm_zone = ps;
66 #endif
67 
68  ot_unix_time = gnulib::mktime (&t);
69 
70 #if defined (HAVE_STRUCT_TM_TM_ZONE)
71  delete [] ps;
72 #endif
73 
74  ot_usec = tm.usec ();
75 }
76 
77 std::string
78 octave_time::ctime (void) const
79 {
80  return octave_localtime (*this) . asctime ();
81 }
82 
83 void
85 {
86  struct timeval tp;
87 
88  gnulib::gettimeofday (&tp, 0);
89 
90  ot_unix_time = tp.tv_sec;
91  ot_usec = tp.tv_usec;
92 }
93 
94 // From the mktime() manual page:
95 //
96 // The mktime() function converts a broken-down time structure,
97 // expressed as local time, to calendar time representation.
98 //
99 // <snip>
100 //
101 // If structure members are outside their legal interval, they
102 // will be normalized (so that, e.g., 40 October is changed into
103 // 9 November).
104 //
105 // So, we no longer check limits here.
106 
107 #define DEFINE_SET_FIELD_FCN(type, f, lo, hi) \
108  octave_base_tm& \
109  octave_base_tm::f (type v) \
110  { \
111  tm_ ## f = v; \
112  \
113  return *this; \
114  }
115 
116 #define DEFINE_SET_INT_FIELD_FCN(f, lo, hi) \
117  DEFINE_SET_FIELD_FCN (int, f, lo, hi)
118 
119 DEFINE_SET_INT_FIELD_FCN (usec, 0, 1000000)
125 DEFINE_SET_INT_FIELD_FCN (year, std::numeric_limits<int>::min (),
126  std::numeric_limitd<int>::max ())
130 DEFINE_SET_FIELD_FCN (long, gmtoff, -86400, 0)
131 
133 octave_base_tm::zone (const std::string& s)
134 {
135  tm_zone = s;
136  return *this;
137 }
138 
139 #if !defined STRFTIME_BUF_INITIAL_SIZE
140 #define STRFTIME_BUF_INITIAL_SIZE 128
141 #endif
142 
143 std::string
144 octave_base_tm::strftime (const std::string& fmt) const
145 {
146  std::string retval;
147 
148  if (! fmt.empty ())
149  {
150  struct tm t;
151 
152  t.tm_sec = tm_sec;
153  t.tm_min = tm_min;
154  t.tm_hour = tm_hour;
155  t.tm_mday = tm_mday;
156  t.tm_mon = tm_mon;
157  t.tm_year = tm_year;
158  t.tm_wday = tm_wday;
159  t.tm_yday = tm_yday;
160  t.tm_isdst = tm_isdst;
161 
162 #if defined (HAVE_STRUCT_TM_GMTOFF)
163  t.tm_gmtoff = tm_gmtoff;
164 #endif
165 
166 #if defined (HAVE_STRUCT_TM_TM_ZONE)
167  char *ps = strsave (tm_zone.c_str ());
168  t.tm_zone = ps;
169 #endif
170 
171  const char *fmt_str = fmt.c_str ();
172 
173  char *buf = 0;
174  size_t bufsize = STRFTIME_BUF_INITIAL_SIZE;
175  size_t chars_written = 0;
176 
177  while (chars_written == 0)
178  {
179  delete [] buf;
180  buf = new char [bufsize];
181  buf[0] = '\0';
182 
183  chars_written = nstrftime (buf, bufsize, fmt_str, &t, 0, 0);
184 
185  bufsize *= 2;
186  }
187 
188 #if defined (HAVE_STRUCT_TM_TM_ZONE)
189  delete [] ps;
190 #endif
191 
192  retval = buf;
193 
194  delete [] buf;
195  }
196 
197  return retval;
198 }
199 
200 void
202 {
203  if (! p)
204  return;
205 
206  struct tm *t = static_cast<struct tm*> (p);
207 
208  tm_sec = t->tm_sec;
209  tm_min = t->tm_min;
210  tm_hour = t->tm_hour;
211  tm_mday = t->tm_mday;
212  tm_mon = t->tm_mon;
213  tm_year = t->tm_year;
214  tm_wday = t->tm_wday;
215  tm_yday = t->tm_yday;
216  tm_isdst = t->tm_isdst;
217 
218 #if defined (HAVE_STRUCT_TM_GMTOFF)
219  tm_gmtoff = t->tm_gmtoff;
220 #endif
221 
222 #if defined (HAVE_STRUCT_TM_TM_ZONE)
223  if (t->tm_zone)
224  tm_zone = t->tm_zone;
225 #elif defined (HAVE_TZNAME)
226  if (t->tm_isdst == 0 || t->tm_isdst == 1)
227  tm_zone = tzname[t->tm_isdst];
228 #endif
229 }
230 
231 void
233 {
234  tm_usec = ot.usec ();
235 
236  time_t t = ot.unix_time ();
237 
238  octave_base_tm::init (localtime (&t));
239 }
240 
241 void
243 {
244  tm_usec = ot.usec ();
245 
246  time_t t = ot.unix_time ();
247 
248  octave_base_tm::init (gmtime (&t));
249 }
250 
251 void
252 octave_strptime::init (const std::string& str, const std::string& fmt)
253 {
254  struct tm t;
255 
256  t.tm_sec = 0;
257  t.tm_min = 0;
258  t.tm_hour = 0;
259  t.tm_mday = 0;
260  t.tm_mon = -1;
261  t.tm_year = std::numeric_limits<int>::min ();
262  t.tm_wday = 0;
263  t.tm_yday = 0;
264  t.tm_isdst = 0;
265 
266 #if defined (HAVE_STRUCT_TM_GMTOFF)
267  t.tm_gmtoff = 0;
268 #endif
269 
270 #if defined (HAVE_STRUCT_TM_TM_ZONE)
271  char *ps = strsave ("");
272  t.tm_zone = ps;
273 #endif
274 
275  const char *p = str.c_str ();
276 
277  char *q = gnulib::strptime (p, fmt.c_str (), &t);
278 
279  // Fill in wday and yday, but only if mday is valid and the mon and year
280  // are filled in, avoiding issues with mktime and invalid dates.
281  if (t.tm_mday != 0 && t.tm_mon >= 0
282  && t.tm_year != std::numeric_limits<int>::min ())
283  {
284  t.tm_isdst = -1;
285  gnulib::mktime (&t);
286  }
287 
288  if (t.tm_mon < 0)
289  t.tm_mon = 0;
290 
291  if (t.tm_year == std::numeric_limits<int>::min ())
292  t.tm_year = 0;
293 
294  if (q)
295  nchars = q - p + 1;
296  else
297  nchars = 0;
298 
300 
301 #if defined (HAVE_STRUCT_TM_TM_ZONE)
302  delete [] ps;
303 #endif
304 }