2 * Copyright (c) 2000-2004,2006,2011-2012,2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
26 // Manage the Tower of Babel of CSSM dates and times
28 #include <security_cdsa_utilities/cssmdates.h>
29 #include <security_cdsa_utilities/cssmerrors.h>
30 #include <Security/cssm.h>
35 // A (private) PODwrapper for CFGregorianDate
37 struct Gregorian
: public PodWrapper
<Gregorian
, CFGregorianDate
> {
40 Gregorian(int y
, int m
, int d
, int h
= 0, int min
= 0, double sec
= 0)
42 year
= y
; month
= m
; day
= d
;
43 hour
= h
; minute
= min
; second
= sec
;
46 Gregorian(CFAbsoluteTime ref
)
47 { static_cast<CFGregorianDate
&>(*this) = CFAbsoluteTimeGetGregorianDate(ref
, NULL
); }
49 operator CFAbsoluteTime () const
50 { return CFGregorianDateGetAbsoluteTime(*this, NULL
); }
55 // The CssmDate PODwrapper
57 CssmDate::CssmDate(const char *y
, const char *m
, const char *d
)
59 assign(years(), 4, y
);
60 assign(months(), 2, m
);
64 CssmDate::CssmDate(int y
, int m
, int d
)
66 // internal format is "yyyymmdd" (no null termination)
68 if (8 != snprintf(str
, 9, "%4.4d%2.2d%2.2d", y
, m
, d
))
69 CssmError::throwMe(CSSM_ERRCODE_UNKNOWN_FORMAT
);
73 int CssmDate::year() const
74 { return atoi(string(years(), 4).c_str()); }
76 int CssmDate::month() const
77 { return atoi(string(months(), 2).c_str()); }
79 int CssmDate::day() const
80 { return atoi(string(days(), 2).c_str()); }
83 void CssmDate::assign(char *dest
, int width
, const char *src
)
85 // pick last width characters of src at most
86 size_t len
= strlen(src
);
88 CssmError::throwMe(CSSM_ERRCODE_UNKNOWN_FORMAT
);
89 memset(dest
, '0', width
- len
);
90 memcpy(dest
+ width
- len
, src
, len
);
95 // CssmUniformDate core functions
100 // Uniform conversions with CFDateRef
102 CssmUniformDate::CssmUniformDate(CFDateRef ref
)
104 mTime
= CFDateGetAbsoluteTime(ref
);
107 CssmUniformDate::operator CFDateRef() const
109 return CFDateCreate(NULL
, mTime
);
114 // Uniform conversions with CssmDates
116 CssmUniformDate::CssmUniformDate(const CssmDate
&date
)
118 mTime
= CFGregorianDateGetAbsoluteTime(Gregorian(date
.year(), date
.month(), date
.day()),
122 CssmUniformDate::operator CssmDate () const
124 Gregorian
greg(mTime
);
125 return CssmDate(greg
.year
, greg
.month
, greg
.day
);
130 // Uniform conversions with CssmData (1999-06-30_15:05:39 form)
132 CssmUniformDate::CssmUniformDate(const CSSM_DATA
&inData
)
134 const CssmData
&data
= CssmData::overlay(inData
);
135 if (data
.length() != 19)
136 CssmError::throwMe(CSSM_ERRCODE_UNKNOWN_FORMAT
);
137 setFromString(reinterpret_cast<const char *>(inData
.Data
), "%ld-%d-%d_%d:%d:%lf", 19);
140 void CssmUniformDate::convertTo(CssmOwnedData
&data
) const
142 Gregorian
greg(mTime
);
144 if (19 != snprintf(str
, 20, "%4.4d-%2.2d-%2.2d_%2.2d:%2.2d:%2.2d",
145 int(greg
.year
), greg
.month
, greg
.day
, greg
.hour
, greg
.minute
, int(greg
.second
)))
146 CssmError::throwMe(CSSM_ERRCODE_UNKNOWN_FORMAT
);
147 data
= CssmData(str
, 19);
152 // Uniform conversions with CSSM_TIMESTRING (19990630150539 form)
154 CssmUniformDate::CssmUniformDate(const char *src
)
156 setFromString(src
, "%4ld%2d%2d%2d%2d%2lf", 14);
159 void CssmUniformDate::convertTo(char *dst
, size_t length
) const
162 CssmError::throwMe(CSSMERR_CSSM_BUFFER_TOO_SMALL
);
163 Gregorian
greg(mTime
);
165 if (14 != snprintf(str
, 15, "%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d",
166 int(greg
.year
), greg
.month
, greg
.day
, greg
.hour
, greg
.minute
, int(greg
.second
)))
167 CssmError::throwMe(CSSM_ERRCODE_UNKNOWN_FORMAT
);
168 memcpy(dst
, str
, length
== 14 ? 14 : 15); // null terminate if there's room
173 // Generalized parse-from-string setup
175 void CssmUniformDate::setFromString(const char *src
, const char *format
, size_t fieldWidth
)
177 // use a stack buffer
179 assert(fieldWidth
< sizeof(str
));
181 // make a copy with proper null terminator
182 memcpy(str
, src
, fieldWidth
);
183 str
[fieldWidth
] = '\0';
185 // parse (with limited checks for bad field formats)
187 int month
, day
, hour
, minute
;
189 if (6 != sscanf(str
, format
,
190 &year
, &month
, &day
, &hour
, &minute
, &second
))
191 CssmError::throwMe(CSSM_ERRCODE_UNKNOWN_FORMAT
);
194 mTime
= Gregorian((int)year
, month
, day
, hour
, minute
, second
);