Coverage Report

Created: 2021-08-22 09:07

/src/skia/third_party/externals/dng_sdk/source/dng_date_time.cpp
Line
Count
Source (jump to first uncovered line)
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.cpp#2 $ */ 
10
/* $DateTime: 2012/06/01 07:28:57 $ */
11
/* $Change: 832715 $ */
12
/* $Author: tknoll $ */
13
14
/*****************************************************************************/
15
16
#include "dng_date_time.h"
17
18
#include "dng_exceptions.h"
19
#include "dng_mutex.h"
20
#include "dng_stream.h"
21
#include "dng_string.h"
22
#include "dng_utils.h"
23
24
#include <time.h>
25
26
#if qMacOS
27
#include <TargetConditionals.h>
28
#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
29
#include <MobileCoreServices/MobileCoreServices.h>
30
#else
31
#include <CoreServices/CoreServices.h>
32
#endif  // TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
33
#endif  // qMacOS
34
35
#if qWinOS
36
#include <windows.h>
37
#endif
38
39
/******************************************************************************/
40
41
// MWG says don't use fake time zones in XMP, but there is some
42
// old software that requires them to work correctly.
43
44
bool gDNGUseFakeTimeZonesInXMP = false;
45
46
/******************************************************************************/
47
48
dng_date_time::dng_date_time ()
49
50
  : fYear   (0)
51
  , fMonth  (0)
52
  , fDay    (0)
53
  , fHour   (0)
54
  , fMinute (0)
55
  , fSecond (0)
56
  
57
23.4k
  {
58
  
59
23.4k
  }
60
61
/******************************************************************************/
62
63
dng_date_time::dng_date_time (uint32 year,
64
                  uint32 month,
65
                  uint32 day,
66
                  uint32 hour,
67
                  uint32 minute,
68
                  uint32 second)
69
70
  : fYear   (year)
71
  , fMonth  (month)
72
  , fDay    (day)
73
  , fHour   (hour)
74
  , fMinute (minute)
75
  , fSecond (second)
76
  
77
0
  {
78
79
0
  }
80
81
/******************************************************************************/
82
83
bool dng_date_time::IsValid () const
84
6.77k
  {
85
  
86
6.77k
  return fYear   >= 1 && fYear   <= 9999 &&
87
527
       fMonth  >= 1 && fMonth  <= 12   &&
88
362
       fDay    >= 1 && fDay    <= 31   &&
89
252
       fHour   <= 23   &&
90
171
       fMinute <= 59   &&
91
162
       fSecond <= 59;
92
  
93
6.77k
  }
94
      
95
/*****************************************************************************/
96
97
void dng_date_time::Clear ()
98
0
  {
99
  
100
0
  *this = dng_date_time ();
101
  
102
0
  }
103
      
104
/*****************************************************************************/
105
106
static uint32 DateTimeParseU32 (const char *&s)
107
6.87k
  {
108
  
109
6.87k
  uint32 x = 0;
110
  
111
10.7k
  while (*s == ' ' || *s == ':')
112
3.82k
    s++;
113
    
114
10.0k
  while (*s >= '0' && *s <= '9')
115
3.18k
    {
116
3.18k
    x = SafeUint32Mult(x, 10);
117
3.18k
    x = SafeUint32Add(x, (uint32) (*(s++) - '0'));
118
3.18k
    }
119
    
120
6.87k
  return x;
121
  
122
6.87k
  }
123
      
124
/*****************************************************************************/
125
126
bool dng_date_time::Parse (const char *s)
127
1.15k
  {
128
  
129
1.15k
  fYear   = DateTimeParseU32 (s);
130
1.15k
  fMonth  = DateTimeParseU32 (s);
131
1.15k
  fDay    = DateTimeParseU32 (s);
132
1.15k
  fHour   = DateTimeParseU32 (s);
133
1.15k
  fMinute = DateTimeParseU32 (s);
134
1.15k
  fSecond = DateTimeParseU32 (s);
135
  
136
1.15k
  return IsValid ();
137
  
138
1.15k
  }
139
      
140
/*****************************************************************************/
141
142
dng_string dng_time_zone::Encode_ISO_8601 () const
143
0
  {
144
  
145
0
  dng_string result;
146
  
147
0
  if (IsValid ())
148
0
    {
149
    
150
0
    if (OffsetMinutes () == 0)
151
0
      {
152
      
153
0
      result.Set ("Z");
154
      
155
0
      }
156
      
157
0
    else
158
0
      {
159
      
160
0
      char s [64];
161
      
162
0
      int offset = OffsetMinutes ();
163
      
164
0
      if (offset > 0)
165
0
        {
166
        
167
0
        sprintf (s, "+%02d:%02d", offset / 60, offset % 60);
168
        
169
0
        }
170
        
171
0
      else
172
0
        {
173
        
174
0
        offset = -offset;
175
        
176
0
        sprintf (s, "-%02d:%02d", offset / 60, offset % 60);
177
        
178
0
        }
179
        
180
0
      result.Set (s);
181
      
182
0
      }
183
  
184
0
    }
185
    
186
0
  return result;
187
    
188
0
  }
189
190
/*****************************************************************************/
191
192
dng_date_time_info::dng_date_time_info ()
193
194
  : fDateOnly   (true)
195
  , fDateTime   ()
196
  , fSubseconds ()
197
  , fTimeZone   ()
198
  
199
21.2k
  {
200
  
201
21.2k
  }
202
    
203
/*****************************************************************************/
204
205
bool dng_date_time_info::IsValid () const
206
5.63k
  {
207
  
208
5.63k
  return fDateTime.IsValid ();
209
  
210
5.63k
  }
211
    
212
/*****************************************************************************/
213
214
void dng_date_time_info::SetDate (uint32 year,
215
                  uint32 month,
216
                  uint32 day)
217
0
  {
218
  
219
0
  fDateTime.fYear  = year;
220
0
  fDateTime.fMonth = month;
221
0
  fDateTime.fDay   = day;
222
  
223
0
  }
224
  
225
/*****************************************************************************/
226
227
void dng_date_time_info::SetTime (uint32 hour,
228
                  uint32 minute,
229
                  uint32 second)
230
0
  {
231
  
232
0
  fDateOnly = false;
233
  
234
0
  fDateTime.fHour   = hour;
235
0
  fDateTime.fMinute = minute;
236
0
  fDateTime.fSecond = second;
237
  
238
0
  }
239
  
240
/*****************************************************************************/
241
242
void dng_date_time_info::Decode_ISO_8601 (const char *s)
243
0
  {
244
  
245
0
  Clear ();
246
    
247
0
  uint32 len = (uint32) strlen (s);
248
  
249
0
  if (!len)
250
0
    {
251
0
    return;
252
0
    }
253
    
254
0
  unsigned year  = 0;
255
0
  unsigned month = 0;
256
0
  unsigned day   = 0;
257
  
258
0
  if (sscanf (s,
259
0
        "%u-%u-%u",
260
0
        &year,
261
0
        &month,
262
0
        &day) != 3)
263
0
    {
264
0
    return;
265
0
    }
266
    
267
0
  SetDate ((uint32) year,
268
0
       (uint32) month,
269
0
       (uint32) day);
270
  
271
0
  if (fDateTime.NotValid ())
272
0
    {
273
0
    Clear ();
274
0
    return;
275
0
    }
276
    
277
0
  for (uint32 j = 0; j < len; j++)
278
0
    {
279
    
280
0
    if (s [j] == 'T')
281
0
      {
282
      
283
0
      unsigned hour   = 0;
284
0
      unsigned minute = 0;
285
0
      unsigned second = 0;
286
      
287
0
      int items = sscanf (s + j + 1,
288
0
                "%u:%u:%u",
289
0
                &hour,
290
0
                &minute,
291
0
                &second);
292
293
0
      if (items >= 2 && items <= 3)
294
0
        {
295
        
296
0
        SetTime ((uint32) hour,
297
0
             (uint32) minute,
298
0
             (uint32) second);
299
        
300
0
        if (fDateTime.NotValid ())
301
0
          {
302
0
          Clear ();
303
0
          return;
304
0
          }
305
          
306
0
        if (items == 3)
307
0
          {
308
          
309
0
          for (uint32 k = j + 1; k < len; k++)
310
0
            {
311
            
312
0
            if (s [k] == '.')
313
0
              {
314
              
315
0
              while (++k < len && s [k] >= '0' && s [k] <= '9')
316
0
                {
317
                
318
0
                char ss [2];
319
                
320
0
                ss [0] = s [k];
321
0
                ss [1] = 0;
322
                
323
0
                fSubseconds.Append (ss);
324
                
325
0
                }
326
              
327
0
              break;
328
              
329
0
              }
330
            
331
0
            }
332
            
333
0
          }
334
          
335
0
        for (uint32 k = j + 1; k < len; k++)
336
0
          {
337
          
338
0
          if (s [k] == 'Z')
339
0
            {
340
            
341
0
            fTimeZone.SetOffsetMinutes (0);
342
            
343
0
            break;
344
            
345
0
            }
346
            
347
0
          if (s [k] == '+' || s [k] == '-')
348
0
            {
349
            
350
0
            int32 sign = (s [k] == '-' ? -1 : 1);
351
            
352
0
            unsigned tzhour = 0;
353
0
            unsigned tzmin  = 0;
354
            
355
0
            if (sscanf (s + k + 1,
356
0
                  "%u:%u",
357
0
                  &tzhour,
358
0
                  &tzmin) > 0)
359
0
              {
360
              
361
0
              fTimeZone.SetOffsetMinutes (sign * (tzhour * 60 + tzmin));
362
                              
363
0
              }
364
            
365
0
            break;
366
            
367
0
            }
368
          
369
0
          }
370
        
371
0
        }
372
        
373
0
      break;
374
    
375
0
      }
376
    
377
0
    }
378
379
0
  }
380
381
/*****************************************************************************/
382
383
dng_string dng_date_time_info::Encode_ISO_8601 () const
384
0
  {
385
  
386
0
  dng_string result;
387
  
388
0
  if (IsValid ())
389
0
    {
390
    
391
0
    char s [256];
392
  
393
0
    sprintf (s,
394
0
         "%04u-%02u-%02u",
395
0
         (unsigned) fDateTime.fYear,
396
0
         (unsigned) fDateTime.fMonth,
397
0
         (unsigned) fDateTime.fDay);
398
         
399
0
    result.Set (s);
400
    
401
0
    if (!fDateOnly)
402
0
      {
403
      
404
0
      sprintf (s,
405
0
           "T%02u:%02u:%02u",
406
0
           (unsigned) fDateTime.fHour,
407
0
           (unsigned) fDateTime.fMinute,
408
0
           (unsigned) fDateTime.fSecond);
409
           
410
0
      result.Append (s);
411
      
412
0
      if (fSubseconds.NotEmpty ())
413
0
        {
414
        
415
0
        bool subsecondsValid = true;
416
        
417
0
        uint32 len = fSubseconds.Length ();
418
        
419
0
        for (uint32 index = 0; index < len; index++)
420
0
          {
421
          
422
0
          if (fSubseconds.Get () [index] < '0' ||
423
0
            fSubseconds.Get () [index] > '9')
424
0
            {
425
0
            subsecondsValid = false;
426
0
            break;
427
0
            }
428
            
429
0
          }
430
      
431
0
        if (subsecondsValid)
432
0
          {
433
0
          result.Append (".");
434
0
          result.Append (fSubseconds.Get ());
435
0
          }
436
          
437
0
        }
438
        
439
0
      if (gDNGUseFakeTimeZonesInXMP)
440
0
        {
441
      
442
        // Kludge: Early versions of the XMP toolkit assume Zulu time
443
        // if the time zone is missing.  It is safer for fill in the
444
        // local time zone. 
445
        
446
0
        dng_time_zone tempZone = fTimeZone;
447
          
448
0
        if (tempZone.NotValid ())
449
0
          {
450
0
          tempZone = LocalTimeZone (fDateTime);
451
0
          }
452
          
453
0
        result.Append (tempZone.Encode_ISO_8601 ().Get ());
454
        
455
0
        }
456
        
457
0
      else
458
0
        {
459
            
460
        // MWG: Now we don't fill in the local time zone.  So only
461
        // add the time zone if it is known and valid.
462
        
463
0
        if (fTimeZone.IsValid ())
464
0
          {
465
0
          result.Append (fTimeZone.Encode_ISO_8601 ().Get ());
466
0
          }
467
          
468
0
        }
469
      
470
0
      }
471
           
472
0
    }
473
  
474
0
  return result;
475
  
476
0
  }
477
  
478
/*****************************************************************************/
479
480
void dng_date_time_info::Decode_IPTC_Date (const char *s)
481
0
  {
482
  
483
0
  if (strlen (s) == 8)
484
0
    {
485
  
486
0
    unsigned year   = 0;
487
0
    unsigned month  = 0;
488
0
    unsigned day    = 0;
489
490
0
    if (sscanf (s,
491
0
          "%4u%2u%2u",
492
0
          &year,
493
0
          &month,
494
0
          &day) == 3)
495
0
      {
496
      
497
0
      SetDate ((uint32) year,
498
0
           (uint32) month,
499
0
           (uint32) day);
500
501
0
      }
502
      
503
0
    }
504
505
0
  }
506
507
/*****************************************************************************/
508
509
dng_string dng_date_time_info::Encode_IPTC_Date () const
510
0
  {
511
  
512
0
  dng_string result;
513
  
514
0
  if (IsValid ())
515
0
    {
516
    
517
0
    char s [64];
518
    
519
0
    sprintf (s,
520
0
           "%04u%02u%02u",
521
0
           (unsigned) fDateTime.fYear,
522
0
           (unsigned) fDateTime.fMonth,
523
0
           (unsigned) fDateTime.fDay);
524
         
525
0
    result.Set (s);
526
           
527
0
    }
528
  
529
0
  return result;
530
  
531
0
  }
532
    
533
/*****************************************************************************/
534
535
void dng_date_time_info::Decode_IPTC_Time (const char *s)
536
0
  {
537
  
538
0
  if (strlen (s) == 11)
539
0
    {
540
    
541
0
    char time [12];
542
    
543
0
    memcpy (time, s, sizeof (time));
544
    
545
0
    if (time [6] == '+' ||
546
0
      time [6] == '-')
547
0
      {
548
    
549
0
      int tzsign = (time [6] == '-') ? -1 : 1;
550
      
551
0
      time [6] = 0;
552
      
553
0
      unsigned hour   = 0;
554
0
      unsigned minute = 0;
555
0
      unsigned second = 0;
556
0
      unsigned tzhour = 0;
557
0
      unsigned tzmin  = 0;
558
      
559
0
      if (sscanf (time,
560
0
            "%2u%2u%2u",
561
0
            &hour,
562
0
            &minute,
563
0
            &second) == 3 &&
564
0
        sscanf (time + 7,
565
0
            "%2u%2u",
566
0
            &tzhour,
567
0
            &tzmin) == 2)
568
0
        {
569
        
570
0
        dng_time_zone zone;
571
        
572
0
        zone.SetOffsetMinutes (tzsign * (tzhour * 60 + tzmin));
573
        
574
0
        if (zone.IsValid ())
575
0
          {
576
        
577
0
          SetTime ((uint32) hour,
578
0
               (uint32) minute,
579
0
               (uint32) second);
580
                        
581
0
          SetZone (zone);
582
          
583
0
          }
584
                        
585
0
        }
586
        
587
0
      }
588
    
589
0
    }
590
    
591
0
  else if (strlen (s) == 6)
592
0
    {
593
    
594
0
    unsigned hour   = 0;
595
0
    unsigned minute = 0;
596
0
    unsigned second = 0;
597
    
598
0
    if (sscanf (s,
599
0
          "%2u%2u%2u",
600
0
          &hour,
601
0
          &minute,
602
0
          &second) == 3)
603
0
      {
604
          
605
0
      SetTime ((uint32) hour,
606
0
           (uint32) minute,
607
0
           (uint32) second);
608
                      
609
0
      }
610
611
0
    }
612
  
613
0
  else if (strlen (s) == 4)
614
0
    {
615
    
616
0
    unsigned hour   = 0;
617
0
    unsigned minute = 0;
618
    
619
0
    if (sscanf (s,
620
0
          "%2u%2u",
621
0
          &hour,
622
0
          &minute) == 2)
623
0
      {
624
          
625
0
      SetTime ((uint32) hour,
626
0
           (uint32) minute,
627
0
           0);
628
                      
629
0
      }
630
631
0
    }
632
633
0
  }
634
    
635
/*****************************************************************************/
636
637
dng_string dng_date_time_info::Encode_IPTC_Time () const
638
0
  {
639
  
640
0
  dng_string result;
641
  
642
0
  if (IsValid () && !fDateOnly)
643
0
    {
644
    
645
0
    char s [64];
646
    
647
0
    if (fTimeZone.IsValid ())
648
0
      {
649
    
650
0
      sprintf (s,
651
0
           "%02u%02u%02u%c%02u%02u",
652
0
           (unsigned) fDateTime.fHour,
653
0
           (unsigned) fDateTime.fMinute,
654
0
           (unsigned) fDateTime.fSecond,
655
0
           (int) (fTimeZone.OffsetMinutes () >= 0 ? '+' : '-'),
656
0
           (unsigned) (Abs_int32 (fTimeZone.OffsetMinutes ()) / 60),
657
0
           (unsigned) (Abs_int32 (fTimeZone.OffsetMinutes ()) % 60));
658
           
659
0
      }
660
      
661
0
    else
662
0
      {
663
      
664
0
      sprintf (s,
665
0
           "%02u%02u%02u",
666
0
           (unsigned) fDateTime.fHour,
667
0
           (unsigned) fDateTime.fMinute,
668
0
           (unsigned) fDateTime.fSecond);
669
           
670
0
      }
671
         
672
0
    result.Set (s);
673
           
674
0
    }
675
  
676
0
  return result;
677
  
678
0
  }
679
    
680
/*****************************************************************************/
681
682
static dng_mutex gDateTimeMutex ("gDateTimeMutex");
683
684
/*****************************************************************************/
685
686
void CurrentDateTimeAndZone (dng_date_time_info &info)
687
0
  {
688
  
689
0
  time_t sec;
690
  
691
0
  time (&sec);
692
  
693
0
  tm t;
694
0
  tm zt;
695
  
696
0
    {
697
    
698
0
    dng_lock_mutex lock (&gDateTimeMutex);
699
    
700
0
    t  = *localtime (&sec);
701
0
    zt = *gmtime    (&sec);
702
    
703
0
    }
704
    
705
0
  dng_date_time dt;
706
    
707
0
  dt.fYear   = t.tm_year + 1900;
708
0
  dt.fMonth  = t.tm_mon + 1;
709
0
  dt.fDay    = t.tm_mday;
710
0
  dt.fHour   = t.tm_hour;
711
0
  dt.fMinute = t.tm_min;
712
0
  dt.fSecond = t.tm_sec;
713
  
714
0
  info.SetDateTime (dt);
715
  
716
0
  int tzHour = t.tm_hour - zt.tm_hour;
717
0
  int tzMin  = t.tm_min  - zt.tm_min;
718
  
719
0
  bool zonePositive = (t.tm_year >  zt.tm_year) ||
720
0
            (t.tm_year == zt.tm_year && t.tm_yday >  zt.tm_yday) ||
721
0
            (t.tm_year == zt.tm_year && t.tm_yday == zt.tm_yday && tzHour > 0) ||
722
0
            (t.tm_year == zt.tm_year && t.tm_yday == zt.tm_yday && tzHour == 0 && tzMin >= 0);
723
            
724
0
  tzMin += tzHour * 60;
725
            
726
0
  if (zonePositive)
727
0
    {
728
    
729
0
    while (tzMin < 0)
730
0
      tzMin += 24 * 60;
731
      
732
0
    }
733
    
734
0
  else
735
0
    {
736
    
737
0
    while (tzMin > 0)
738
0
      tzMin -= 24 * 60;
739
    
740
0
    }
741
    
742
0
  dng_time_zone zone;
743
    
744
0
  zone.SetOffsetMinutes (tzMin);
745
  
746
0
  info.SetZone (zone);
747
  
748
0
  }
749
750
/*****************************************************************************/
751
752
void DecodeUnixTime (uint32 unixTime, dng_date_time &dt)
753
0
  {
754
  
755
0
  time_t sec = (time_t) unixTime;
756
  
757
0
  tm t;
758
  
759
0
    {
760
    
761
0
    dng_lock_mutex lock (&gDateTimeMutex);
762
    
763
    #if qMacOS && !defined(__MACH__)
764
    
765
    // Macintosh CFM stores time in local time zone.
766
767
    tm *tp = localtime (&sec);
768
    
769
    #else
770
    
771
    // Macintosh Mach-O and Windows stores time in Zulu time.
772
    
773
0
    tm *tp = gmtime (&sec);
774
    
775
0
    #endif
776
    
777
0
    if (!tp)
778
0
      {
779
0
      dt.Clear ();
780
0
      return;
781
0
      }
782
      
783
0
    t = *tp;
784
    
785
0
    }
786
  
787
0
  dt.fYear   = t.tm_year + 1900;
788
0
  dt.fMonth  = t.tm_mon + 1;
789
0
  dt.fDay    = t.tm_mday;
790
0
  dt.fHour   = t.tm_hour;
791
0
  dt.fMinute = t.tm_min;
792
0
  dt.fSecond = t.tm_sec;
793
794
0
  }
795
796
/*****************************************************************************/
797
798
dng_time_zone LocalTimeZone (const dng_date_time &dt)
799
0
  {
800
  
801
0
  dng_time_zone result;
802
  
803
0
  if (dt.IsValid ())
804
0
    {
805
    
806
    #if qMacOS
807
    
808
    CFTimeZoneRef zoneRef = CFTimeZoneCopyDefault ();
809
    
810
    if (zoneRef)
811
      {
812
      
813
      CFGregorianDate gregDate;
814
815
      gregDate.year   = dt.fYear;
816
      gregDate.month  = (SInt8) dt.fMonth;
817
      gregDate.day    = (SInt8) dt.fDay;
818
      gregDate.hour   = (SInt8) dt.fHour;
819
      gregDate.minute = (SInt8) dt.fMinute;
820
      gregDate.second = (SInt8) dt.fSecond;
821
      
822
      CFAbsoluteTime absTime = CFGregorianDateGetAbsoluteTime (gregDate, zoneRef);
823
      
824
      CFTimeInterval secondsDelta = CFTimeZoneGetSecondsFromGMT (zoneRef, absTime);
825
    
826
      CFRelease (zoneRef);
827
      
828
      result.SetOffsetSeconds (Round_int32 (secondsDelta));
829
      
830
      if (result.IsValid ())
831
        {
832
        return result;
833
        }
834
      
835
      }
836
    
837
    #endif
838
    
839
    #if qWinOS
840
    
841
    if (GetTimeZoneInformation          != NULL &&
842
      SystemTimeToTzSpecificLocalTime != NULL &&
843
        SystemTimeToFileTime            != NULL)
844
      {
845
      
846
      TIME_ZONE_INFORMATION tzInfo;
847
      
848
      DWORD x = GetTimeZoneInformation (&tzInfo);
849
      
850
      SYSTEMTIME localST;
851
      
852
      memset (&localST, 0, sizeof (localST));
853
854
      localST.wYear   = (WORD) dt.fYear;
855
      localST.wMonth  = (WORD) dt.fMonth;
856
      localST.wDay    = (WORD) dt.fDay;
857
      localST.wHour   = (WORD) dt.fHour;
858
      localST.wMinute = (WORD) dt.fMinute;
859
      localST.wSecond = (WORD) dt.fSecond;
860
      
861
      SYSTEMTIME utcST;
862
863
      if (TzSpecificLocalTimeToSystemTime (&tzInfo, &localST, &utcST))
864
        {
865
        
866
        FILETIME localFT;
867
        FILETIME utcFT;
868
        
869
        (void) SystemTimeToFileTime (&localST, &localFT);
870
        (void) SystemTimeToFileTime (&utcST  , &utcFT  );
871
        
872
        uint64 time1 = (((uint64) localFT.dwHighDateTime) << 32) + localFT.dwLowDateTime;
873
        uint64 time2 = (((uint64) utcFT  .dwHighDateTime) << 32) + utcFT  .dwLowDateTime;
874
        
875
        // FILETIMEs are in units to 100 ns.  Convert to seconds.
876
        
877
        int64 time1Sec = time1 / 10000000;
878
        int64 time2Sec = time2 / 10000000;
879
      
880
        int32 delta = (int32) (time1Sec - time2Sec);
881
882
        result.SetOffsetSeconds (delta);
883
          
884
        if (result.IsValid ())
885
          {
886
          return result;
887
          }
888
      
889
        }
890
      
891
      }
892
    
893
    #endif
894
    
895
0
    }
896
  
897
  // Figure out local time zone.
898
  
899
0
  dng_date_time_info current_info;
900
  
901
0
  CurrentDateTimeAndZone (current_info);
902
  
903
0
  result = current_info.TimeZone ();
904
    
905
0
  return result;
906
      
907
0
  }
908
909
/*****************************************************************************/
910
911
dng_date_time_storage_info::dng_date_time_storage_info ()
912
913
  : fOffset (kDNGStreamInvalidOffset     )
914
  , fFormat (dng_date_time_format_unknown)
915
  
916
21.2k
  {
917
  
918
21.2k
  }
919
920
/*****************************************************************************/
921
922
dng_date_time_storage_info::dng_date_time_storage_info (uint64 offset,
923
                            dng_date_time_format format)
924
      
925
  : fOffset (offset)
926
  , fFormat (format)
927
  
928
440
  {
929
  
930
440
  }
931
932
/*****************************************************************************/
933
934
bool dng_date_time_storage_info::IsValid () const
935
0
  {
936
  
937
0
  return fOffset != kDNGStreamInvalidOffset;
938
  
939
0
  }
940
941
/*****************************************************************************/
942
943
uint64 dng_date_time_storage_info::Offset () const
944
0
  {
945
  
946
0
  if (!IsValid ())
947
0
    ThrowProgramError ();
948
    
949
0
  return fOffset;
950
  
951
0
  }
952
953
/*****************************************************************************/
954
955
dng_date_time_format dng_date_time_storage_info::Format () const
956
0
  {
957
  
958
0
  if (!IsValid ())
959
0
    ThrowProgramError ();
960
    
961
0
  return fFormat;
962
  
963
0
  }
964
965
/*****************************************************************************/