1/*****************************************************************************/
2// Copyright 2006-2008 Adobe Systems Incorporated
3// All Rights Reserved.
4//
5// NOTICE: Adobe permits you to use, modify, and distribute this file in
6// accordance with the terms of the Adobe license agreement accompanying it.
7/*****************************************************************************/
8
9/* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_date_time.h#1 $ */
10/* $DateTime: 2012/05/30 13:28:51 $ */
11/* $Change: 832332 $ */
12/* $Author: tknoll $ */
13
14/** \file
15 * Functions and classes for working with dates and times in DNG files.
16 */
17
18/*****************************************************************************/
19
20#ifndef __dng_date_time__
21#define __dng_date_time__
22
23/*****************************************************************************/
24
25#include "dng_classes.h"
26#include "dng_string.h"
27#include "dng_types.h"
28
29/*****************************************************************************/
30
31/// \brief Class for holding a date/time and converting to and from relevant
32/// date/time formats
33
34class dng_date_time
35 {
36
37 public:
38
39 uint32 fYear;
40 uint32 fMonth;
41 uint32 fDay;
42 uint32 fHour;
43 uint32 fMinute;
44 uint32 fSecond;
45
46 public:
47
48 /// Construct an invalid date/time
49
50 dng_date_time ();
51
52 /// Construct a date/time with specific values.
53 /// \param year Year to use as actual integer value, such as 2006.
54 /// \param month Month to use from 1 - 12, where 1 is January.
55 /// \param day Day of month to use from 1 -31, where 1 is the first.
56 /// \param hour Hour of day to use from 0 - 23, where 0 is midnight.
57 /// \param minute Minute of hour to use from 0 - 59.
58 /// \param second Second of minute to use from 0 - 59.
59
60 dng_date_time (uint32 year,
61 uint32 month,
62 uint32 day,
63 uint32 hour,
64 uint32 minute,
65 uint32 second);
66
67 /// Predicate to determine if a date is valid.
68 /// \retval true if all fields are within range.
69
70 bool IsValid () const;
71
72 /// Predicate to determine if a date is invalid.
73 /// \retval true if any field is out of range.
74
75 bool NotValid () const
76 {
77 return !IsValid ();
78 }
79
80 /// Equal operator.
81
82 bool operator== (const dng_date_time &dt) const
83 {
84 return fYear == dt.fYear &&
85 fMonth == dt.fMonth &&
86 fDay == dt.fDay &&
87 fHour == dt.fHour &&
88 fMinute == dt.fMinute &&
89 fSecond == dt.fSecond;
90 }
91
92 // Not-equal operator.
93
94 bool operator!= (const dng_date_time &dt) const
95 {
96 return !(*this == dt);
97 }
98
99 /// Set date to an invalid value.
100
101 void Clear ();
102
103 /// Parse an EXIF format date string.
104 /// \param s Input date string to parse.
105 /// \retval true if date was parsed successfully and date is valid.
106
107 bool Parse (const char *s);
108
109 };
110
111/*****************************************************************************/
112
113/// \brief Class for holding a time zone.
114
115class dng_time_zone
116 {
117
118 private:
119
120 enum
121 {
122
123 kMaxOffsetHours = 15,
124 kMinOffsetHours = -kMaxOffsetHours,
125
126 kMaxOffsetMinutes = kMaxOffsetHours * 60,
127 kMinOffsetMinutes = kMinOffsetHours * 60,
128
129 kInvalidOffset = kMinOffsetMinutes - 1
130
131 };
132
133 // Offset from GMT in minutes. Positive numbers are
134 // ahead of GMT, negative number are behind GMT.
135
136 int32 fOffsetMinutes;
137
138 public:
139
140 dng_time_zone ()
141 : fOffsetMinutes (kInvalidOffset)
142 {
143 }
144
145 void Clear ()
146 {
147 fOffsetMinutes = kInvalidOffset;
148 }
149
150 void SetOffsetHours (int32 offset)
151 {
152 fOffsetMinutes = SafeInt32Mult(offset, 60);
153 }
154
155 void SetOffsetMinutes (int32 offset)
156 {
157 fOffsetMinutes = offset;
158 }
159
160 void SetOffsetSeconds (int32 offset)
161 {
162 fOffsetMinutes = (offset > 0) ? ((offset + 30) / 60)
163 : ((offset - 30) / 60);
164 }
165
166 bool IsValid () const
167 {
168 return fOffsetMinutes >= kMinOffsetMinutes &&
169 fOffsetMinutes <= kMaxOffsetMinutes;
170 }
171
172 bool NotValid () const
173 {
174 return !IsValid ();
175 }
176
177 int32 OffsetMinutes () const
178 {
179 return fOffsetMinutes;
180 }
181
182 bool IsExactHourOffset () const
183 {
184 return IsValid () && ((fOffsetMinutes % 60) == 0);
185 }
186
187 int32 ExactHourOffset () const
188 {
189 return fOffsetMinutes / 60;
190 }
191
192 dng_string Encode_ISO_8601 () const;
193
194 };
195
196/*****************************************************************************/
197
198/// \brief Class for holding complete data/time/zone information.
199
200class dng_date_time_info
201 {
202
203 private:
204
205 // Is only the date valid and not the time?
206
207 bool fDateOnly;
208
209 // Date and time.
210
211 dng_date_time fDateTime;
212
213 // Subseconds string (stored in a separate tag in EXIF).
214
215 dng_string fSubseconds;
216
217 // Time zone, if known.
218
219 dng_time_zone fTimeZone;
220
221 public:
222
223 dng_date_time_info ();
224
225 bool IsValid () const;
226
227 bool NotValid () const
228 {
229 return !IsValid ();
230 }
231
232 void Clear ()
233 {
234 *this = dng_date_time_info ();
235 }
236
237 const dng_date_time & DateTime () const
238 {
239 return fDateTime;
240 }
241
242 void SetDateTime (const dng_date_time &dt)
243 {
244 fDateOnly = false;
245 fDateTime = dt;
246 }
247
248 const dng_string & Subseconds () const
249 {
250 return fSubseconds;
251 }
252
253 void SetSubseconds (const dng_string &s)
254 {
255 fSubseconds = s;
256 }
257
258 const dng_time_zone & TimeZone () const
259 {
260 return fTimeZone;
261 }
262
263 void SetZone (const dng_time_zone &zone)
264 {
265 fTimeZone = zone;
266 }
267
268 void Decode_ISO_8601 (const char *s);
269
270 dng_string Encode_ISO_8601 () const;
271
272 void Decode_IPTC_Date (const char *s);
273
274 dng_string Encode_IPTC_Date () const;
275
276 void Decode_IPTC_Time (const char *s);
277
278 dng_string Encode_IPTC_Time () const;
279
280 private:
281
282 void SetDate (uint32 year,
283 uint32 month,
284 uint32 day);
285
286 void SetTime (uint32 hour,
287 uint32 minute,
288 uint32 second);
289
290 };
291
292/*****************************************************************************/
293
294/// Get the current date/time and timezone.
295/// \param info Receives current data/time/zone.
296
297void CurrentDateTimeAndZone (dng_date_time_info &info);
298
299/*****************************************************************************/
300
301/// Convert UNIX "seconds since Jan 1, 1970" time to a dng_date_time
302
303void DecodeUnixTime (uint32 unixTime, dng_date_time &dt);
304
305/*****************************************************************************/
306
307/// Return timezone of current location at a given date.
308/// \param dt Date at which to compute timezone difference. (For example, used
309/// to determine Daylight Savings, etc.)
310/// \retval Time zone for date/time dt.
311
312dng_time_zone LocalTimeZone (const dng_date_time &dt);
313
314/*****************************************************************************/
315
316/// Tag to encode date represenation format
317
318enum dng_date_time_format
319 {
320 dng_date_time_format_unknown = 0, /// Date format not known
321 dng_date_time_format_exif = 1, /// EXIF date string
322 dng_date_time_format_unix_little_endian = 2, /// 32-bit UNIX time as 4-byte little endian
323 dng_date_time_format_unix_big_endian = 3 /// 32-bit UNIX time as 4-byte big endian
324 };
325
326/*****************************************************************************/
327
328/// \brief Store file offset from which date was read.
329///
330/// Used internally by Adobe to update date in original file.
331/// \warning Use at your own risk.
332
333class dng_date_time_storage_info
334 {
335
336 private:
337
338 uint64 fOffset;
339
340 dng_date_time_format fFormat;
341
342 public:
343
344 /// The default constructor initializes to an invalid state.
345
346 dng_date_time_storage_info ();
347
348 /// Construct with file offset and date format.
349
350 dng_date_time_storage_info (uint64 offset,
351 dng_date_time_format format);
352
353 /// Predicate to determine if an offset is valid.
354 /// \retval true if offset is valid.
355
356 bool IsValid () const;
357
358 // The accessors throw if the data is not valid.
359
360 /// Getter for offset in file.
361 /// \exception dng_exception with fErrorCode equal to dng_error_unknown
362 /// if offset is not valid.
363
364 uint64 Offset () const;
365
366 /// Get for format date was originally stored in file. Throws a
367 /// dng_error_unknown exception if offset is invalid.
368 /// \exception dng_exception with fErrorCode equal to dng_error_unknown
369 /// if offset is not valid.
370
371 dng_date_time_format Format () const;
372
373 };
374
375/*****************************************************************************/
376
377// Kludge: Global boolean to turn on fake time zones in XMP for old software.
378
379extern bool gDNGUseFakeTimeZonesInXMP;
380
381/*****************************************************************************/
382
383#endif
384
385/*****************************************************************************/
386