bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
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
36static char rcsid[] not_used ="$Id$";
37
38#include <string>
39#include <sstream>
40#include <iomanip>
41
42#include <libdap/BaseType.h>
43#include "DODS_Time.h"
44#include <libdap/debug.h>
45#include <libdap/Error.h>
46
47using namespace std;
48
49double DODS_Time::_eps = 1.0e-6;
50
51static string time_syntax_string = \
52"Invalid time: times must be given as hh:mm or hh:mm:ss with an optional\n\
53suffix of GMT or UTC. In addition, 0 <= hh <=23, 0 <= mm <= 59 and\n\
540 <= ss <= 59.999999";
55
56static inline double
57compute_ssm(int hh, int mm, double ss)
58{
59 return ((hh * 60 + mm) * 60) + ss;
60}
61
62static string
63extract_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
84bool
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
93double
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
104DODS_Time::DODS_Time(): _hours(0), _minutes(0), _seconds(-1),
105 _sec_since_midnight(-1), _gmt(false)
106{
107}
108
109DODS_Time::DODS_Time(string time_str)
110{
111 set(time_str);
112}
113
115{
116 set(extract_argument(arg));
117}
118
119DODS_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
129DODS_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
139void
140DODS_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
183void
184DODS_Time::set(BaseType *arg)
185{
186 set(extract_argument(arg));
187}
188
189void
190DODS_Time::set(int hh, int mm, bool gmt)
191{
192 set(hh, mm, 0, gmt);
193}
194
195void
196DODS_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
210double
212{
213 return _eps;
214}
215
216void
218{
219 _eps = eps;
220}
221
222int
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
229int
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
239int
244
245int
247{
248 return t1 > t2 || t1 == t2;
249}
250
251int
253{
255}
256
257int
259{
260 return t1 < t2 || t1 == t2;
261}
262
263double
265{
266 return _sec_since_midnight;
267}
268
269int
271{
272 return _hours;
273}
274
275int
277{
278 return _minutes;
279}
280
281double
283{
284 return _seconds;
285}
286
287bool
289{
290 return _gmt;
291}
292
293string
294DODS_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
int hours() const
Definition DODS_Time.cc:270
double seconds() const
Definition DODS_Time.cc:282
friend int operator<(DODS_Time &t1, DODS_Time &t2)
Less-than.
Definition DODS_Time.cc:252
double seconds_since_midnight() const
Definition DODS_Time.cc:264
string get(bool gmt=true) const
Definition DODS_Time.cc:294
friend int operator!=(DODS_Time &t1, DODS_Time &t2)
Inequality.
Definition DODS_Time.cc:230
friend int operator>(DODS_Time &t1, DODS_Time &t2)
Greater-than.
Definition DODS_Time.cc:240
void set(string time)
Definition DODS_Time.cc:140
bool OK() const
Definition DODS_Time.cc:85
void set_epsilon(double eps)
Definition DODS_Time.cc:217
friend int operator<=(DODS_Time &t1, DODS_Time &t2)
Less-than or Equal-to.
Definition DODS_Time.cc:258
DODS_Time(string time)
bool gmt() const
Definition DODS_Time.cc:288
friend int operator==(DODS_Time &t1, DODS_Time &t2)
Equality.
Definition DODS_Time.cc:223
int minutes() const
Definition DODS_Time.cc:276
double fraction() const
Definition DODS_Time.cc:94
double get_epsilon() const
Definition DODS_Time.cc:211
friend int operator>=(DODS_Time &t1, DODS_Time &t2)
Greater-than or Equal-to.
Definition DODS_Time.cc:246