2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
20 File: cssmdatetime.cpp
22 Contains: CSSM date and time utilities for the Mac
24 Written by: The Hindsight team
26 Copyright: © 1997-2000 by Apple Computer, Inc., all rights reserved.
28 Change History (most recent first):
34 #define _CPP_CSSM_DATE_TIME_UTILS
37 #include "cssmdatetime.h"
41 #include <Security/utilities.h>
42 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
43 #include <CoreFoundation/CFDate.h>
44 #include <CoreFoundation/CFTimeZone.h>
50 namespace CSSMDateTimeUtils
53 #define MAX_TIME_STR_LEN 30
54 #define UTC_TIME_STRLEN 13
55 #define GENERALIZED_TIME_STRLEN 15
59 GetCurrentMacLongDateTime(SInt64
&outMacDate
)
61 CFTimeZoneRef timeZone
= CFTimeZoneCopyDefault();
62 CFAbsoluteTime absTime
= CFAbsoluteTimeGetCurrent();
63 absTime
+= CFTimeZoneGetSecondsFromGMT(timeZone
, absTime
);
65 outMacDate
= SInt64(double(absTime
+ kCFAbsoluteTimeIntervalSince1904
));
69 TimeStringToMacSeconds (const CSSM_DATA
&inUTCTime
, UInt32
&ioMacDate
)
72 TimeStringToMacLongDateTime(inUTCTime
, ldt
);
73 ioMacDate
= UInt32(ldt
);
77 * Given a CSSM_DATA containing either a UTC-style or "generalized time"
78 * time string, convert to 32-bit Mac time in seconds.
79 * Returns nonzero on error.
82 TimeStringToMacLongDateTime (const CSSM_DATA
&inUTCTime
, SInt64
&outMacDate
)
92 ::memset( &date
, 0, sizeof(date
) );
94 if ((inUTCTime
.Data
== NULL
) || (inUTCTime
.Length
== 0))
96 MacOSError::throwMe(paramErr
);
99 /* tolerate NULL terminated or not */
100 len
= inUTCTime
.Length
;
101 if (inUTCTime
.Data
[len
- 1] == '\0')
106 case UTC_TIME_STRLEN
: // 2-digit year, not Y2K compliant
109 case GENERALIZED_TIME_STRLEN
: // 4-digit year
112 default: // unknown format
113 MacOSError::throwMe(paramErr
);
116 cp
= (char *)inUTCTime
.Data
;
118 /* check that all characters except last are digits */
119 for(i
=0; i
<(sint32
)(len
- 1); i
++) {
120 if ( !(isdigit(cp
[i
])) ) {
121 MacOSError::throwMe(paramErr
);
125 /* check last character is a 'Z' */
126 if(cp
[len
- 1] != 'Z' ) {
127 MacOSError::throwMe(paramErr
);
134 /* two more digits */
146 * 0 <= year <= 50 : assume century 21
147 * 50 < year < 70 : illegal per PKIX
148 * 70 < year <= 99 : assume century 20
154 MacOSError::throwMe(paramErr
);
156 /* else century 20, OK */
158 /* bug fix... we need to end up with a 4-digit year! */
161 /* by definition - tm_year is year - 1900 */
162 //tmp->tm_year = x - 1900;
170 /* in the string, months are from 1 to 12 */
171 if((x
> 12) || (x
<= 0)) {
172 MacOSError::throwMe(paramErr
);
174 /* in a tm, 0 to 11 */
175 //tmp->tm_mon = x - 1;
183 /* 1..31 in both formats */
184 if((x
> 31) || (x
<= 0)) {
185 MacOSError::throwMe(paramErr
);
195 if((x
> 23) || (x
< 0)) {
196 MacOSError::throwMe(paramErr
);
206 if((x
> 59) || (x
< 0)) {
207 MacOSError::throwMe(paramErr
);
217 if((x
> 59) || (x
< 0)) {
218 MacOSError::throwMe(paramErr
);
223 CFTimeZoneRef timeZone
= CFTimeZoneCreateWithTimeIntervalFromGMT(NULL
, 0);
224 CFAbsoluteTime absTime
= CFGregorianDateGetAbsoluteTime(date
, timeZone
);
227 // Adjust abstime to local timezone
228 timeZone
= CFTimeZoneCopyDefault();
229 absTime
+= CFTimeZoneGetSecondsFromGMT(timeZone
, absTime
);
232 outMacDate
= SInt64(double(absTime
+ kCFAbsoluteTimeIntervalSince1904
));
235 void MacSecondsToTimeString(UInt32 inMacDate
, UInt32 inLength
, void *outData
)
237 SInt64 ldt
= SInt64(UInt64(inMacDate
));
238 MacLongDateTimeToTimeString(ldt
, inLength
, outData
);
241 void MacLongDateTimeToTimeString(const SInt64
&inMacDate
,
242 UInt32 inLength
, void *outData
)
244 // @@@ this code is close, but on the fringe case of a daylight savings time it will be off for a little while
245 CFAbsoluteTime absTime
= inMacDate
- kCFAbsoluteTimeIntervalSince1904
;
247 // Remove local timezone component from absTime
248 CFTimeZoneRef timeZone
= CFTimeZoneCopyDefault();
249 absTime
-= CFTimeZoneGetSecondsFromGMT(timeZone
, absTime
);
252 timeZone
= CFTimeZoneCreateWithTimeIntervalFromGMT(NULL
, 0);
253 CFGregorianDate date
= CFAbsoluteTimeGetGregorianDate(absTime
, timeZone
);
258 sprintf((char *)(outData
), "%04d%02d%02d%02d%02d%02dZ",
259 int(date
.year
% 10000), date
.month
, date
.day
,
260 date
.hour
, date
.minute
, int(date
.second
));
262 else if (inLength
== 14)
264 /* UTC - 2 year digits - code which parses this assumes that
265 * (2-digit) years between 0 and 49 are in century 21 */
266 sprintf((char *)(outData
), "%02d%02d%02d%02d%02d%02dZ",
267 int(date
.year
% 100), date
.month
, date
.day
,
268 date
.hour
, date
.minute
, int(date
.second
));
271 MacOSError::throwMe(paramErr
);
274 }; // end namespace CSSMDateTimeUtils
276 } // end namespace Security