28#define TIME_BUF_SIZE 21
43 memset(&t, 0,
sizeof(
struct tm));
44 if (!icalgmtime_r(&now, &t)) {
45 return vcardtime_null_datetime();
48 tt.year = t.tm_year + 1900;
49 tt.month = t.tm_mon + 1;
61 return (t.year == -1 && t.month == -1 && t.day == -1);
66 return (t.hour == -1 && t.minute == -1 && t.second == -1);
71 return (vcardtime_is_time(t) && vcardtime_is_date(t));
76 return (t.day != -1 && t.hour != -1);
81 return (t.year != -1 && t.month != -1 && t.day != -1 &&
82 t.hour != -1 && t.minute != -1 && t.second != -1 &&
88 return (t.utcoffset == 0 && !vcardtime_is_date(t));
91bool vcardtime_is_leap_year(
const int year)
95 }
else if (year <= 1752) {
96 return (year % 4 == 0);
98 return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
102static const int days_in_month[] =
103 {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
109 if (t.year > 3000 || t.day == 0 ||
110 t.hour > 23 || t.minute > 59 || t.second > 60 ||
111 t.utcoffset < -720 || t.utcoffset > 840) {
115 if (t.minute == -1 && t.hour != -1 && t.second != -1) {
124 if (t.year != -1 && t.day != -1) {
132 days = 28 + vcardtime_is_leap_year(t.year);
140 days = days_in_month[t.month];
151#pragma GCC diagnostic push
152#pragma GCC diagnostic ignored "-Wformat-nonliteral"
153static int sprintf_date(
const vcardtimetype t,
unsigned flags,
154 char *buf,
size_t size)
164 if (!(flags & VCARDTIME_AS_V4)) {
165 return snprintf(buf, size,
"%04d%02d%02d",
166 t.year == -1 ? 0 : t.year,
167 t.month == -1 ? 1 : t.month,
168 t.day == -1 ? 1 : t.day);
169 }
else if (t.year != -1) {
172 }
else if (t.day == -1) {
175 fmt =
"%04d%02d%02d";
179 return snprintf(buf, size, fmt, t.year, t.month, t.day);
180 }
else if (t.month != -1) {
188 return snprintf(buf, size, fmt, t.month, t.day);
190 return snprintf(buf, size,
"---%02d", t.day);
194static int sprintf_time(
const vcardtimetype t,
unsigned flags,
195 char *buf,
size_t size)
205 if (!(flags & VCARDTIME_BARE_TIME)) {
206 strncat(buf,
"T", size);
211 if (!(flags & VCARDTIME_AS_V4)) {
212 n = snprintf(buf, size,
"%02d%02d%02d",
213 t.hour == -1 ? 0 : t.hour,
214 t.minute == -1 ? 0 : t.minute,
215 t.second == -1 ? 0 : t.second);
216 }
else if (t.hour != -1) {
218 if (t.minute == -1) {
221 }
else if (t.second == -1) {
226 fmt =
"%02d%02d%02d";
230 n = snprintf(buf, size, fmt, t.hour, t.minute, t.second);
231 }
else if (t.minute != -1) {
233 if (t.second == -1) {
242 return snprintf(buf, size, fmt, t.minute, t.second);
245 return snprintf(buf, size,
"--%02d", t.second);
248 if (t.utcoffset != -1) {
253 if (t.utcoffset == 0) {
254 strncpy(buf,
"Z", size);
257 n += snprintf(buf, size,
"%+03d%02d",
258 t.utcoffset / 60, abs(t.utcoffset % 60));
264#pragma GCC diagnostic pop
266char *vcardtime_as_vcard_string_r(
const vcardtimetype t,
unsigned flags)
268 size_t size = TIME_BUF_SIZE;
273 if (!(flags & VCARDTIME_AS_V4) || !vcardtime_is_time(t)) {
274 int n = sprintf_date(t, flags, ptr, size);
278 if (!vcardtime_is_date(t)) {
279 (void)sprintf_time(t, flags, ptr, size);
285const char *vcardtime_as_vcard_string(
const vcardtimetype t,
unsigned flags)
289 buf = vcardtime_as_vcard_string_r(t, flags);
294#define num_digits(s) strspn(s, "0123456789")
296static const char *sscanf_date(
const char *str,
vcardtimetype *t)
312 }
else if (!strncmp(str,
"--", 2)) {
316 ndig = num_digits(month + 1);
319 sscanf(str,
"---%2u%n", (
unsigned *)&t->day, &nchar);
322 ndig = num_digits(month);
325 sscanf(str,
"--%2u%2u%n",
326 (
unsigned *)&t->month, (
unsigned *)&t->day, &nchar);
327 }
else if (ndig == 2) {
328 sscanf(str,
"--%2u%n", (
unsigned *)&t->month, &nchar);
332 ndig = num_digits(str);
335 sscanf(str,
"%4u%2u%2u%n",
336 (
unsigned *)&t->year, (
unsigned *)&t->month,
337 (
unsigned *)&t->day, &nchar);
338 }
else if (ndig == 4) {
342 sscanf(str,
"%4u%n", (
unsigned *)&t->year, &nchar);
343 }
else if (*month ==
'-') {
344 ndig = num_digits(++month);
347 if (month[2] ==
'-') {
348 sscanf(str,
"%4u-%2u-%2u%n",
349 (
unsigned *)&t->year, (
unsigned *)&t->month,
350 (
unsigned *)&t->day, &nchar);
352 sscanf(str,
"%4u-%2u%n",
353 (
unsigned *)&t->year, (
unsigned *)&t->month,
366 newstr = (
char *)str + nchar;
370static const char *sscanf_zone(
const char *str,
vcardtimetype *t)
376 unsigned offset_h = 0, offset_m = 0;
384 }
else if (*str ==
'Z') {
386 }
else if (strchr(
"+-", *str)) {
387 size_t ndig = num_digits(str + 1);
390 sscanf(str,
"%1[+-]%2u%2u%n", sign, &offset_h, &offset_m, &nchar);
391 }
else if (ndig == 2) {
392 sscanf(str,
"%1[+-]%2u%n", sign, &offset_h, &nchar);
401 t->utcoffset = (int)(60 * offset_h + offset_m);
403 t->utcoffset = -t->utcoffset;
406 newstr = (
char *)str + nchar;
410static const char *sscanf_time(
const char *str,
vcardtimetype *t)
425 }
else if (*str ==
'-') {
427 ndig = num_digits(str + 2);
430 sscanf(str,
"--%2u%n", (
unsigned *)&t->second, &nchar);
433 ndig = num_digits(str + 1);
436 sscanf(str,
"-%2u%2u%n",
437 (
unsigned *)&t->minute, (
unsigned *)&t->second, &nchar);
438 }
else if (ndig == 2) {
439 sscanf(str,
"-%2u%n", (
unsigned *)&t->minute, &nchar);
444 ndig = num_digits(str);
447 sscanf(str,
"%2u%2u%2u%n",
448 (
unsigned *)&t->hour, (
unsigned *)&t->minute,
449 (
unsigned *)&t->second, &nchar);
450 }
else if (ndig == 4) {
451 sscanf(str,
"%2u%2u%n",
452 (
unsigned *)&t->hour, (
unsigned *)&t->minute, &nchar);
454 }
else if (ndig == 2) {
457 sscanf(str,
"%2u:%2u:%2u.%u%n",
458 (
unsigned *)&t->hour, (
unsigned *)&t->minute,
459 (
unsigned *)&t->second, (
unsigned *)&secfrac, &nchar);
461 sscanf(str,
"%2u:%2u:%2u%n",
462 (
unsigned *)&t->hour, (
unsigned *)&t->minute,
463 (
unsigned *)&t->second, &nchar);
466 sscanf(str,
"%2u%n", (
unsigned *)&t->hour, &nchar);
478 if (t->hour != -1 && *str) {
479 str = sscanf_zone(str, t);
485vcardtimetype vcardtime_from_string(
const char *str,
int is_bare_time)
489 if (!is_bare_time && str && *str !=
'T') {
490 str = sscanf_date(str, &t);
496 str = sscanf_time(str, &t);
499 return (str && !*str) ? t : vcardtime_null_datetime();
void * icalmemory_new_buffer(size_t size)
Creates new buffer with the specified size.
void icalmemory_add_tmp_buffer(void *buf)
Adds an externally allocated buffer to the ring.
Common memory management routines.
Defines the data structure for representing date-times.
Defines the data structure representing vCard date-times.