Home | History | Annotate | Download | only in source
      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 
     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 
    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 
    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 
    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 
    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