bes  Updated for version 3.20.6
DODS_Time.cc
1 
2 // -*- mode: c++; c-basic-offset:4 -*-
3 
4 // This file is part of ff_handler a FreeForm API handler for the OPeNDAP
5 // DAP2 data server.
6 
7 // Copyright (c) 2005 OPeNDAP, Inc.
8 // Author: James Gallagher <jgallagher@opendap.org>
9 //
10 // This is free software; you can redistribute it and/or modify it under the
11 // terms of the GNU Lesser General Public License as published by the Free
12 // Software Foundation; either version 2.1 of the License, or (at your
13 // option) any later version.
14 //
15 // This software is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
18 // License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public
21 // License along with this library; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 //
24 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
25 
26 // (c) COPYRIGHT URI/MIT 1998
27 // Please read the full copyright statement in the file COPYRIGHT.
28 //
29 // Authors:
30 // jhrg,jimg James Gallagher (jgallagher@gso.uri.edu)
31 
32 // Implementation of the DODS Time class
33 
34 #include "config_ff.h"
35 
36 static char rcsid[] not_used ="$Id$";
37 
38 #include <string>
39 #include <sstream>
40 #include <iomanip>
41 
42 #include "BaseType.h"
43 #include "DODS_Time.h"
44 #include "debug.h"
45 #include "Error.h"
46 
47 using namespace std;
48 
49 double DODS_Time::_eps = 1.0e-6;
50 
51 static string time_syntax_string = \
52 "Invalid time: times must be given as hh:mm or hh:mm:ss with an optional\n\
53 suffix of GMT or UTC. In addition, 0 <= hh <=23, 0 <= mm <= 59 and\n\
54 0 <= ss <= 59.999999";
55 
56 static inline double
57 compute_ssm(int hh, int mm, double ss)
58 {
59  return ((hh * 60 + mm) * 60) + ss;
60 }
61 
62 static string
63 extract_argument(BaseType *arg)
64 {
65 #ifndef TEST
66  if (arg->type() != dods_str_c)
67  throw Error(malformed_expr, "A DODS string argument is required.");
68 
69  // Use String until conversion of String to string is complete. 9/3/98
70  // jhrg
71  string *sp = NULL;
72  arg->buf2val((void **)&sp);
73  string s = sp->c_str();
74  delete sp;
75 
76  DBG(cerr << "s: " << s << endl);
77 
78  return s;
79 #else
80  return "";
81 #endif
82 }
83 
84 bool
86 {
87  // _hours and _minutes are unsigned.
88  return /* _hours >= 0 && */ _hours <= 23
89  /* && _minutes >= 0 */ && _minutes <= 59
90  && _seconds >= 0.0 && _seconds < 60.0;
91 }
92 
93 double
95 {
96  return ((_hours + ((_minutes + (_seconds / 60.0)) / 60.0)) / 24.0);
97 }
98 
99 // Public mfincs.
100 
101 // Don't test this ctor with OK since a null Time is not OK for use but we
102 // want to be able to make one and then call set_time(). 12/16/98 jhrg
103 
104 DODS_Time::DODS_Time(): _hours(0), _minutes(0), _seconds(-1),
105  _sec_since_midnight(-1), _gmt(false)
106 {
107 }
108 
109 DODS_Time::DODS_Time(string time_str)
110 {
111  set(time_str);
112 }
113 
114 DODS_Time::DODS_Time(BaseType *arg)
115 {
116  set(extract_argument(arg));
117 }
118 
119 DODS_Time::DODS_Time(dods_uint32 hh, dods_uint32 mm, bool gmt):
120  _hours(hh), _minutes(mm), _seconds(0), _gmt(gmt)
121 {
122  _sec_since_midnight = compute_ssm(hh, mm, 0);
123 #ifndef TEST
124  if (!OK())
125  throw Error(malformed_expr, time_syntax_string);
126 #endif
127 }
128 
129 DODS_Time::DODS_Time(dods_uint32 hh, dods_uint32 mm, double ss, bool gmt):
130  _hours(hh), _minutes(mm), _seconds(ss), _gmt(gmt)
131 {
132  _sec_since_midnight = compute_ssm(hh, mm, ss);
133 #ifndef TEST
134  if (!OK())
135  throw Error(malformed_expr, time_syntax_string);
136 #endif
137 }
138 
139 void
140 DODS_Time::set(string time)
141 {
142  // Parse the date_str.
143  istringstream iss(time.c_str());
144  char c;
145  size_t pos1, pos2;
146  iss >> _hours;
147 
148  pos1 = time.find(":");
149  // If there is at least one colon, assume hours:minutes
150  if (pos1 != time.npos) {
151  iss >> c;
152  iss >> _minutes;
153 
154  // If there are two colons, assume hours:minutes:seconds.
155  pos2 = time.rfind(":");
156  if ((pos2 != time.npos) && (pos1 != pos2)) {
157  iss >> c;
158  iss >> _seconds;
159  }
160  else _seconds = 0;
161  }
162  else {
163  // If there are no colons, assume hours only, set others to 0.
164  _minutes = 0;
165  _seconds = 0;
166  }
167  _sec_since_midnight = compute_ssm(_hours, _minutes, _seconds);
168 
169  string gmt;
170  iss >> gmt;
171  if (gmt == "GMT" || gmt == "gmt" || gmt == "UTC"
172  || gmt == "utc")
173  _gmt = true;
174  else
175  _gmt = false;
176 
177 #ifndef TEST
178  if (!OK())
179  throw Error(malformed_expr, time_syntax_string);
180 #endif
181 }
182 
183 void
184 DODS_Time::set(BaseType *arg)
185 {
186  set(extract_argument(arg));
187 }
188 
189 void
190 DODS_Time::set(int hh, int mm, bool gmt)
191 {
192  set(hh, mm, 0, gmt);
193 }
194 
195 void
196 DODS_Time::set(int hh, int mm, double ss, bool gmt)
197 {
198  _hours = hh;
199  _minutes = mm;
200  _seconds = ss;
201  _gmt = gmt;
202  _sec_since_midnight = compute_ssm(hh, mm, ss);
203 
204 #ifndef TEST
205  if (!OK())
206  throw Error(malformed_expr, time_syntax_string);
207 #endif
208 }
209 
210 double
212 {
213  return _eps;
214 }
215 
216 void
218 {
219  _eps = eps;
220 }
221 
222 int
223 operator==(DODS_Time &t1, DODS_Time &t2)
224 {
225  return t1.seconds_since_midnight()+t1._eps >= t2.seconds_since_midnight()
226  && t1.seconds_since_midnight()-t1._eps <= t2.seconds_since_midnight();
227 }
228 
229 int
230 operator!=(DODS_Time &t1, DODS_Time &t2)
231 {
232  return !(t1 == t2);
233 }
234 
235 // The relational ops > and < are possibly flaky. Note that the Intel machines
236 // and the Sparc machines *do* represent floating point numbers slightly
237 // differently.
238 
239 int
240 operator>(DODS_Time &t1, DODS_Time &t2)
241 {
243 }
244 
245 int
246 operator>=(DODS_Time &t1, DODS_Time &t2)
247 {
248  return t1 > t2 || t1 == t2;
249 }
250 
251 int
252 operator<(DODS_Time &t1, DODS_Time &t2)
253 {
255 }
256 
257 int
258 operator<=(DODS_Time &t1, DODS_Time &t2)
259 {
260  return t1 < t2 || t1 == t2;
261 }
262 
263 double
265 {
266  return _sec_since_midnight;
267 }
268 
269 int
271 {
272  return _hours;
273 }
274 
275 int
277 {
278  return _minutes;
279 }
280 
281 double
283 {
284  return _seconds;
285 }
286 
287 bool
289 {
290  return _gmt;
291 }
292 
293 string
294 DODS_Time::get(bool) const
295 {
296  ostringstream oss;
297  // Pad with leading zeros and use fixed fields of two chars for hours and
298  // minutes. Make sure that seconds < 10 have a leading zero but don't
299  // require their filed to have `precision' digits if they are all zero.
300  oss << setfill('0') << setw(2) << _hours << ":"
301  << setfill('0') << setw(2) << _minutes << ":"
302  << setfill('0') << setw(2) << setprecision(6) << _seconds;
303 
304  if (_gmt)
305  oss << " GMT";
306 
307  return oss.str();
308 }
309 
310 // $Log: DODS_Time.cc,v $
311 // Revision 1.15 2004/07/09 17:54:24 jimg
312 // Merged with release-3-4-3FCS.
313 //
314 // Revision 1.11.4.2 2004/03/07 22:05:51 rmorris
315 // Final code changes to port the freeform server to win32.
316 //
317 // Revision 1.14 2004/02/04 20:50:08 jimg
318 // Build fixes. No longer uses Pix.
319 //
320 // Revision 1.13 2003/12/08 21:58:52 edavis
321 // Merge release-3-4 into trunk
322 //
323 // Revision 1.11.4.1 2003/06/29 05:35:10 rmorris
324 // Use standard template library headers correctly and add missing usage
325 // statements.
326 //
327 // Revision 1.12 2003/05/14 19:23:13 jimg
328 // Changed from strstream to sstream.
329 //
330 // Revision 1.11 2003/02/10 23:01:52 jimg
331 // Merged with 3.2.5
332 //
333 // Revision 1.10 2001/09/28 23:19:43 jimg
334 // Merged with 3.2.3.
335 //
336 // Revision 1.9.2.3 2002/12/18 23:30:42 pwest
337 // gcc3.2 compile corrections, mainly regarding the using statement
338 //
339 // Revision 1.9.2.2 2002/01/22 02:19:35 jimg
340 // Fixed bug 62. Users built fmt files that used types other than int32
341 // for date and time components (e.g. int16). I fixed the factory classes
342 // so that DODS_Date and DODS_Time objects will be built correctly when
343 // any of the integer (or in the case of seconds, float) data types are
344 // used. In so doing I also refactored the factory classes so that code
345 // duplication was reduced (by using inhertiance).
346 // Added two tests for the new capabilities (see date_time.1.exp, the last
347 // two tests).
348 //
349 // Revision 1.9.2.1 2001/05/23 18:26:31 dan
350 // Modified to support year/month date representations,
351 // and to support ISO8601 output formats.
352 //
353 // Revision 1.9 2000/10/11 19:37:55 jimg
354 // Moved the CVS log entries to the end of files.
355 // Changed the definition of the read method to match the dap library.
356 // Added exception handling.
357 // Added exceptions to the read methods.
358 //
359 // Revision 1.8 2000/08/31 22:16:54 jimg
360 // Merged with 3.1.7
361 //
362 // Revision 1.6.2.2 2000/08/31 21:31:43 jimg
363 // Merged changes from the trunk (rev 1.7).
364 //
365 // Revision 1.7 2000/08/31 02:53:18 dan
366 // Modified DODS_Time::set(time_str) to handle hours only
367 // time strings. This is part of ISO8601 time specifications
368 // and how JPL stores their daily 9KM Pathfinder archives.
369 //
370 // Revision 1.6.2.1 2000/08/03 20:18:57 jimg
371 // Removed config_dap.h and replaced it with config_ff.h (in *.cc files;
372 // neither should be included in a header file).
373 // Changed code that calculated leap year information so that it uses the
374 // functions in date_proc.c/h.
375 //
376 // Revision 1.6 1999/07/22 21:28:09 jimg
377 // Merged changes from the release-3-0-2 branch
378 //
379 // Revision 1.5.2.2 1999/06/07 17:33:06 edavis
380 // Changed 'data()' to 'c_str()'.
381 //
382 // Revision 1.5.2.1 1999/06/01 15:38:06 jimg
383 // Added code to parse and return floating point dates.
384 //
385 // Revision 1.5 1999/05/27 17:02:22 jimg
386 // Merge with alpha-3-0-0
387 //
388 // Revision 1.4.2.1 1999/05/20 21:38:08 edavis
389 // Fix spelling of COPYRIGHT and remove some #if 0 stuff.
390 //
391 // Revision 1.4 1999/05/04 02:55:35 jimg
392 // Merge with no-gnu
393 //
394 // Revision 1.3.8.1 1999/05/01 04:40:28 brent
395 // converted old String.h to the new std C++ <string> code
396 //
397 // Revision 1.3 1999/01/05 00:35:55 jimg
398 // Removed string class; replaced with the GNU String class. It seems those
399 // don't mix well.
400 // Switched to simpler method names.
401 //
402 // Revision 1.2 1998/12/30 06:38:26 jimg
403 // Define TEST to use this without the dap++ library (e.g., when testing
404 // DODS_Date_Time).
405 //
406 // Revision 1.1 1998/12/28 19:07:33 jimg
407 // Initial version of the DODS_Time object
DODS_Time
Definition: DODS_Time.h:63
DODS_Time::gmt
bool gmt() const
Definition: DODS_Time.cc:288
DODS_Time::DODS_Time
DODS_Time()
Definition: DODS_Time.cc:104
DODS_Time::seconds_since_midnight
double seconds_since_midnight() const
Definition: DODS_Time.cc:264
DODS_Time::hours
int hours() const
Definition: DODS_Time.cc:270
DODS_Time::seconds
double seconds() const
Definition: DODS_Time.cc:282
DODS_Time::set
void set(string time)
Definition: DODS_Time.cc:140
DODS_Time::get_epsilon
double get_epsilon() const
Definition: DODS_Time.cc:211
DODS_Time::set_epsilon
void set_epsilon(double eps)
Definition: DODS_Time.cc:217
DODS_Time::OK
bool OK() const
Definition: DODS_Time.cc:85
DODS_Time::minutes
int minutes() const
Definition: DODS_Time.cc:276
Error
DODS_Time::fraction
double fraction() const
Definition: DODS_Time.cc:94
DODS_Time::get
string get(bool gmt=true) const
Definition: DODS_Time.cc:294