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 34 class 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 NotValid()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 115 class 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 dng_time_zone()140 dng_time_zone () 141 : fOffsetMinutes (kInvalidOffset) 142 { 143 } 144 Clear()145 void Clear () 146 { 147 fOffsetMinutes = kInvalidOffset; 148 } 149 SetOffsetHours(int32 offset)150 void SetOffsetHours (int32 offset) 151 { 152 fOffsetMinutes = SafeInt32Mult(offset, 60); 153 } 154 SetOffsetMinutes(int32 offset)155 void SetOffsetMinutes (int32 offset) 156 { 157 fOffsetMinutes = offset; 158 } 159 SetOffsetSeconds(int32 offset)160 void SetOffsetSeconds (int32 offset) 161 { 162 fOffsetMinutes = (offset > 0) ? ((offset + 30) / 60) 163 : ((offset - 30) / 60); 164 } 165 IsValid()166 bool IsValid () const 167 { 168 return fOffsetMinutes >= kMinOffsetMinutes && 169 fOffsetMinutes <= kMaxOffsetMinutes; 170 } 171 NotValid()172 bool NotValid () const 173 { 174 return !IsValid (); 175 } 176 OffsetMinutes()177 int32 OffsetMinutes () const 178 { 179 return fOffsetMinutes; 180 } 181 IsExactHourOffset()182 bool IsExactHourOffset () const 183 { 184 return IsValid () && ((fOffsetMinutes % 60) == 0); 185 } 186 ExactHourOffset()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 200 class 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 NotValid()227 bool NotValid () const 228 { 229 return !IsValid (); 230 } 231 Clear()232 void Clear () 233 { 234 *this = dng_date_time_info (); 235 } 236 DateTime()237 const dng_date_time & DateTime () const 238 { 239 return fDateTime; 240 } 241 SetDateTime(const dng_date_time & dt)242 void SetDateTime (const dng_date_time &dt) 243 { 244 fDateOnly = false; 245 fDateTime = dt; 246 } 247 Subseconds()248 const dng_string & Subseconds () const 249 { 250 return fSubseconds; 251 } 252 SetSubseconds(const dng_string & s)253 void SetSubseconds (const dng_string &s) 254 { 255 fSubseconds = s; 256 } 257 TimeZone()258 const dng_time_zone & TimeZone () const 259 { 260 return fTimeZone; 261 } 262 SetZone(const dng_time_zone & zone)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 297 void CurrentDateTimeAndZone (dng_date_time_info &info); 298 299 /*****************************************************************************/ 300 301 /// Convert UNIX "seconds since Jan 1, 1970" time to a dng_date_time 302 303 void 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 312 dng_time_zone LocalTimeZone (const dng_date_time &dt); 313 314 /*****************************************************************************/ 315 316 /// Tag to encode date represenation format 317 318 enum 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 333 class 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 379 extern bool gDNGUseFakeTimeZonesInXMP; 380 381 /*****************************************************************************/ 382 383 #endif 384 385 /*****************************************************************************/ 386