oct-time.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 1999-2012 John W. Eaton
00004 
00005 This file is part of Octave.
00006 
00007 Octave is free software; you can redistribute it and/or modify it
00008 under the terms of the GNU General Public License as published by the
00009 Free Software Foundation; either version 3 of the License, or (at your
00010 option) any later version.
00011 
00012 Octave is distributed in the hope that it will be useful, but WITHOUT
00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Octave; see the file COPYING.  If not, see
00019 <http://www.gnu.org/licenses/>.
00020 
00021 */
00022 
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026 
00027 #include <climits>
00028 #include <ctime>
00029 
00030 #include <sys/time.h>
00031 #include <sys/types.h>
00032 #include <unistd.h>
00033 
00034 #include "strftime.h"
00035 
00036 #include "lo-error.h"
00037 #include "lo-math.h"
00038 #include "lo-utils.h"
00039 #include "oct-locbuf.h"
00040 #include "oct-time.h"
00041 
00042 octave_time::octave_time (const octave_base_tm& tm)
00043   : ot_unix_time (), ot_usec ()
00044 {
00045   struct tm t;
00046 
00047   t.tm_sec = tm.sec ();
00048   t.tm_min = tm.min ();
00049   t.tm_hour = tm.hour ();
00050   t.tm_mday = tm.mday ();
00051   t.tm_mon = tm.mon ();
00052   t.tm_year = tm.year ();
00053   t.tm_wday = tm.wday ();
00054   t.tm_yday = tm.yday ();
00055   t.tm_isdst = tm.isdst ();
00056 
00057 #if defined (HAVE_STRUCT_TM_GMTOFF)
00058   t.tm_gmtoff = tm.gmtoff ();
00059 #endif
00060 
00061 #if defined (HAVE_STRUCT_TM_TM_ZONE)
00062   std::string s = tm.zone ();
00063   char *ps = strsave (s.c_str ());
00064   t.tm_zone = ps;
00065 #endif
00066 
00067   ot_unix_time = gnulib::mktime (&t);
00068 
00069 #if defined (HAVE_STRUCT_TM_TM_ZONE)
00070   delete [] ps;
00071 #endif
00072 
00073   ot_usec = tm.usec ();
00074 }
00075 
00076 std::string
00077 octave_time::ctime (void) const
00078 {
00079   return octave_localtime (*this) . asctime ();
00080 }
00081 
00082 void
00083 octave_time::stamp (void)
00084 {
00085   struct timeval tp;
00086 
00087   gnulib::gettimeofday (&tp, 0);
00088 
00089   ot_unix_time = tp.tv_sec;
00090   ot_usec = tp.tv_usec;
00091 }
00092 
00093 // From the mktime() manual page:
00094 //
00095 //     The  mktime()  function converts a broken-down time structure,
00096 //     expressed as local time, to calendar time representation.
00097 //
00098 //     <snip>
00099 //
00100 //     If structure members are outside  their  legal interval, they
00101 //     will be normalized (so that, e.g., 40 October is changed into
00102 //     9 November).
00103 //
00104 // So, we no longer check limits here.
00105 
00106 #define DEFINE_SET_FIELD_FCN(type, f, lo, hi) \
00107   octave_base_tm& \
00108   octave_base_tm::f (type v) \
00109   { \
00110     tm_ ## f = v; \
00111  \
00112     return *this; \
00113   }
00114 
00115 #define DEFINE_SET_INT_FIELD_FCN(f, lo, hi) \
00116   DEFINE_SET_FIELD_FCN (int, f, lo, hi)
00117 
00118 DEFINE_SET_INT_FIELD_FCN (usec, 0, 1000000)
00119 DEFINE_SET_INT_FIELD_FCN (sec, 0, 61)
00120 DEFINE_SET_INT_FIELD_FCN (min, 0, 59)
00121 DEFINE_SET_INT_FIELD_FCN (hour, 0, 23)
00122 DEFINE_SET_INT_FIELD_FCN (mday, 1, 31)
00123 DEFINE_SET_INT_FIELD_FCN (mon, 0, 11)
00124 DEFINE_SET_INT_FIELD_FCN (year, INT_MIN, INT_MAX)
00125 DEFINE_SET_INT_FIELD_FCN (wday, 0, 6)
00126 DEFINE_SET_INT_FIELD_FCN (yday, 0, 365)
00127 DEFINE_SET_INT_FIELD_FCN (isdst, 0, 1)
00128 DEFINE_SET_FIELD_FCN (long, gmtoff, -86400, 0)
00129 
00130 octave_base_tm&
00131 octave_base_tm::zone (const std::string& s)
00132 {
00133   tm_zone = s;
00134   return *this;
00135 }
00136 
00137 #if !defined STRFTIME_BUF_INITIAL_SIZE
00138 #define STRFTIME_BUF_INITIAL_SIZE 128
00139 #endif
00140 
00141 std::string
00142 octave_base_tm::strftime (const std::string& fmt) const
00143 {
00144   std::string retval;
00145 
00146   if (! fmt.empty ())
00147     {
00148       struct tm t;
00149 
00150       t.tm_sec = tm_sec;
00151       t.tm_min = tm_min;
00152       t.tm_hour = tm_hour;
00153       t.tm_mday = tm_mday;
00154       t.tm_mon = tm_mon;
00155       t.tm_year = tm_year;
00156       t.tm_wday = tm_wday;
00157       t.tm_yday = tm_yday;
00158       t.tm_isdst = tm_isdst;
00159 
00160 #if defined (HAVE_STRUCT_TM_GMTOFF)
00161       t.tm_gmtoff = tm_gmtoff;
00162 #endif
00163 
00164 #if defined (HAVE_STRUCT_TM_TM_ZONE)
00165       char *ps = strsave (tm_zone.c_str ());
00166       t.tm_zone = ps;
00167 #endif
00168 
00169       const char *fmt_str = fmt.c_str ();
00170 
00171       char *buf = 0;
00172       size_t bufsize = STRFTIME_BUF_INITIAL_SIZE;
00173       size_t chars_written = 0;
00174 
00175       while (chars_written == 0)
00176         {
00177           delete [] buf;
00178           buf = new char[bufsize];
00179           buf[0] = '\0';
00180 
00181           chars_written = nstrftime (buf, bufsize, fmt_str, &t, 0, 0);
00182 
00183           bufsize *= 2;
00184         }
00185 
00186 #if defined (HAVE_STRUCT_TM_TM_ZONE)
00187       delete [] ps;
00188 #endif
00189 
00190       retval = buf;
00191 
00192       delete [] buf;
00193     }
00194 
00195   return retval;
00196 }
00197 
00198 void
00199 octave_base_tm::init (void *p)
00200 {
00201   if (! p)
00202     return;
00203 
00204   struct tm *t = static_cast<struct tm*> (p);
00205 
00206   tm_sec = t->tm_sec;
00207   tm_min = t->tm_min;
00208   tm_hour = t->tm_hour;
00209   tm_mday = t->tm_mday;
00210   tm_mon = t->tm_mon;
00211   tm_year = t->tm_year;
00212   tm_wday = t->tm_wday;
00213   tm_yday = t->tm_yday;
00214   tm_isdst = t->tm_isdst;
00215 
00216 #if defined (HAVE_STRUCT_TM_GMTOFF)
00217   tm_gmtoff = t->tm_gmtoff;
00218 #endif
00219 
00220 #if defined (HAVE_STRUCT_TM_TM_ZONE)
00221   if (t->tm_zone)
00222     tm_zone = t->tm_zone;
00223 #elif defined (HAVE_TZNAME)
00224   if (t->tm_isdst == 0 || t->tm_isdst == 1)
00225     tm_zone = tzname[t->tm_isdst];
00226 #endif
00227 }
00228 
00229 void
00230 octave_localtime::init (const octave_time& ot)
00231 {
00232   tm_usec = ot.usec ();
00233 
00234   time_t t = ot.unix_time ();
00235 
00236   octave_base_tm::init (localtime (&t));
00237 }
00238 
00239 void
00240 octave_gmtime::init (const octave_time& ot)
00241 {
00242   tm_usec = ot.usec ();
00243 
00244   time_t t = ot.unix_time ();
00245 
00246   octave_base_tm::init (gmtime (&t));
00247 }
00248 
00249 void
00250 octave_strptime::init (const std::string& str, const std::string& fmt)
00251 {
00252   struct tm t;
00253 
00254   t.tm_sec = 0;
00255   t.tm_min = 0;
00256   t.tm_hour = 0;
00257   t.tm_mday = 0;
00258   t.tm_mon = -1;
00259   t.tm_year = INT_MIN;
00260   t.tm_wday = 0;
00261   t.tm_yday = 0;
00262   t.tm_isdst = 0;
00263 
00264 #if defined (HAVE_STRUCT_TM_GMTOFF)
00265   t.tm_gmtoff = 0;
00266 #endif
00267 
00268 #if defined (HAVE_STRUCT_TM_TM_ZONE)
00269   char *ps = strsave ("");
00270   t.tm_zone = ps;
00271 #endif
00272 
00273   const char *p = str.c_str ();
00274 
00275   char *q = gnulib::strptime (p, fmt.c_str (), &t);
00276 
00277   // Fill in wday and yday, but only if mday is valid and the mon and year
00278   // are filled in, avoiding issues with mktime and invalid dates.
00279   if (t.tm_mday != 0 && t.tm_mon >= 0 && t.tm_year != INT_MIN)
00280     {
00281       t.tm_isdst = -1;
00282       gnulib::mktime (&t);
00283     }
00284 
00285   if (t.tm_mon < 0)
00286     t.tm_mon = 0;
00287 
00288   if (t.tm_year == INT_MIN)
00289     t.tm_year = 0;
00290 
00291   if (q)
00292     nchars = q - p + 1;
00293   else
00294     nchars = 0;
00295 
00296   octave_base_tm::init (&t);
00297 
00298 #if defined (HAVE_STRUCT_TM_TM_ZONE)
00299   delete [] ps;
00300 #endif
00301 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines