Libical API Documentation 4.0 STABLE VERSION Visit the v3.0 documentation
Loading...
Searching...
No Matches
icaltime.c
Go to the documentation of this file.
1/*======================================================================
2 FILE: icaltime.c
3 CREATOR: eric 02 June 2000
4
5 SPDX-FileCopyrightText: 2000, Eric Busboom <eric@civicknowledge.com>
6 SPDX-License-Identifier: LGPL-2.1-only OR MPL-2.0
7
8 The timegm code is Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
9
10 The Original Code is eric. The Initial Developer of the Original
11 Code is Eric Busboom
12
13 The timegm code in this file is copyrighted by NLNET LABS 2001-2006,
14 according to the following conditions:
15
16 * Redistributions of source code must retain the above copyright notice,
17 this list of conditions and the following disclaimer.
18
19 * Redistributions in binary form must reproduce the above copyright notice,
20 this list of conditions and the following disclaimer in the documentation
21 * and/or other materials provided with the distribution.
22
23 * Neither the name of the NLNET LABS nor the names of its contributors may
24 be used to endorse or promote products derived from this software without
25 specific prior written permission.
26
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
31 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 POSSIBILITY OF SUCH DAMAGE.
38======================================================================*/
39
44
45#ifdef HAVE_CONFIG_H
46#include <config.h>
47#endif
48
49#include "icaltime.h"
50#include "icaldate_p.h"
51#include "icalerror_p.h"
52#include "icalerror.h"
53#include "icalmemory.h"
54#include "icaltimezone.h"
55
56#include <ctype.h>
57#include <stdlib.h>
58
59/* The first array is for non-leap years, the second for leap years*/
60static const int days_in_year_passed_month[2][13] = {
61 /* jan feb mar apr may jun jul aug sep oct nov dec */
62 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
63 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}};
64
65static int icaltime_leap_days(int y1, int y2)
66{
67 --y1;
68 --y2;
69 return (y2 / 4 - y1 / 4) - (y2 / 100 - y1 / 100) + (y2 / 400 - y1 / 400);
70}
71
72/*
73 * Function to convert a struct tm time specification
74 * to an ANSI-compatible icaltime_t using the specified time zone.
75 * This is different from the standard mktime() function
76 * in that we don't want the automatic adjustments for
77 * local daylight savings time applied to the result.
78 * This function expects well-formed input.
79 *
80 * The out_time_t is to store the result, it can be NULL.
81 * Returns false on failure, true on success.
82 */
83static bool make_time(const struct tm *tm, int tzm, icaltime_t *out_time_t)
84{
85 icaltime_t tim;
86 int febs;
87
88 static const int days[] = {-1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364};
89
90 /* check that month specification within range */
91
92 if (tm->tm_mon < 0 || tm->tm_mon > 11) {
93 return false;
94 }
95
96 if (tm->tm_year < 2) {
97 return false;
98 }
99
100#if (SIZEOF_ICALTIME_T == 4)
101 /* check that year specification within range */
102
103 if (tm->tm_year > 138) {
104 return false;
105 }
106
107 /* check for upper bound of Jan 17, 2038 (to avoid possibility of 32-bit arithmetic overflow) */
108 if (tm->tm_year == 138) {
109 if (tm->tm_mon > 0) {
110 return false;
111 } else if (tm->tm_mday > 17) {
112 return false;
113 }
114 }
115#else
116 /* We don't support years >= 10000, because the function has not been tested at this range. */
117 if (tm->tm_year >= 8100) {
118 return false;
119 }
120#endif /* SIZEOF_ICALTIME_T */
121
122 /*
123 * calculate elapsed days since start of the epoch (midnight Jan
124 * 1st, 1970 UTC) 17 = number of leap years between 1900 and 1970
125 * (number of leap days to subtract)
126 */
127
128 tim = (icaltime_t)((tm->tm_year - 70) * 365 + ((tm->tm_year - 1) / 4) - 17);
129
130 /* adjust: no leap days every 100 years, except every 400 years. */
131
132 febs = (tm->tm_year - 100) - ((tm->tm_mon <= 1) ? 1 : 0);
133 tim -= febs / 100;
134 tim += febs / 400;
135
136 /* add number of days elapsed in the current year */
137
138 tim += days[tm->tm_mon];
139
140 /* check and adjust for leap years */
141
142 if ((tm->tm_year & 3) == 0 && tm->tm_mon > 1) {
143 tim += 1;
144 }
145
146 /* elapsed days to current date */
147
148 tim += tm->tm_mday;
149
150 /* calculate elapsed hours since start of the epoch */
151
152 tim = tim * 24 + tm->tm_hour;
153
154 /* calculate elapsed minutes since start of the epoch */
155
156 tim = tim * 60 + tm->tm_min;
157
158 /* adjust per time zone specification */
159
160 tim -= tzm;
161
162 /* calculate elapsed seconds since start of the epoch */
163
164 tim = tim * 60 + tm->tm_sec;
165
166 /* return number of seconds since start of the epoch */
167
168 if (out_time_t) {
169 *out_time_t = tim;
170 }
171
172 return true;
173}
174
175/*
176 * Code adapted from Python 2.4.1 sources (Lib/calendar.py).
177 */
178static icaltime_t icaltime_timegm(const struct tm *tm)
179{
180 int year;
181 icaltime_t days;
182 icaltime_t hours;
183 icaltime_t minutes;
184 icaltime_t seconds;
185
186 /* Validate the tm structure by passing it through make_time() */
187 if (!make_time(tm, 0, NULL)) {
188 /* we have some invalid data in the tm struct */
189 return 0;
190 }
191
192 year = 1900 + tm->tm_year;
193 int idays = (365 * (year - 1970) + icaltime_leap_days(1970, year));
194 days = (icaltime_t)idays;
195 days += days_in_year_passed_month[0][tm->tm_mon];
196
197 if (tm->tm_mon > 1 && icaltime_is_leap_year(year)) {
198 ++days;
199 }
200
201 days += tm->tm_mday - 1;
202 hours = days * 24 + tm->tm_hour;
203 minutes = hours * 60 + tm->tm_min;
204 seconds = minutes * 60 + tm->tm_sec;
205
206 return seconds;
207}
208
209struct icaltimetype icaltime_from_timet_with_zone(const icaltime_t tm, const bool is_date,
210 const icaltimezone *zone)
211{
212 struct icaltimetype tt;
213 struct tm t;
214 icaltimezone *utc_zone;
215
217
218 /* Convert the icaltime_t to a struct tm in UTC time. We can trust gmtime for this. */
219 memset(&t, 0, sizeof(struct tm));
220 if (!icalgmtime_r(&tm, &t)) {
221 return is_date ? icaltime_null_date() : icaltime_null_time();
222 }
223
224 tt.year = t.tm_year + 1900;
225 tt.month = t.tm_mon + 1;
226 tt.day = t.tm_mday;
227 tt.hour = t.tm_hour;
228 tt.minute = t.tm_min;
229 tt.second = t.tm_sec;
230 tt.is_date = 0;
231 tt.is_daylight = 0;
232 tt.zone = (zone == NULL) ? NULL : utc_zone;
233
234 /* Use our timezone functions to convert to the required timezone. */
235 icaltimezone_convert_time(&tt, utc_zone, (icaltimezone *)zone);
236
237 tt.is_date = is_date;
238
239 /* If it is a DATE value, make sure hour, minute & second are 0. */
240 if (is_date) {
241 tt.hour = 0;
242 tt.minute = 0;
243 tt.second = 0;
244 }
245
246 return tt;
247}
248
253
255{
256 return icaltime_from_timet_with_zone(icaltime(NULL), 1, NULL);
257}
258
259icaltime_t icaltime_as_timet(const struct icaltimetype tt)
260{
261 struct tm stm;
262 icaltime_t t = (icaltime_t)-1;
263
264 /* If the time is the special null time, return 0. */
265 if (icaltime_is_null_time(tt)) {
266 return 0;
267 }
268
269 /* Copy the icaltimetype to a struct tm. */
270 memset(&stm, 0, sizeof(struct tm));
271
272 if (icaltime_is_date(tt)) {
273 stm.tm_sec = stm.tm_min = stm.tm_hour = 0;
274 } else {
275 stm.tm_sec = tt.second;
276 stm.tm_min = tt.minute;
277 stm.tm_hour = tt.hour;
278 }
279
280 stm.tm_mday = tt.day;
281 stm.tm_mon = tt.month - 1;
282 stm.tm_year = tt.year - 1900;
283 stm.tm_isdst = -1;
284
285 if (!make_time(&stm, 0, &t)) {
286 t = ((icaltime_t)-1);
287 }
288
289 return t;
290}
291
292icaltime_t icaltime_as_timet_with_zone(const struct icaltimetype tt, const icaltimezone *zone)
293{
294 icaltimezone *utc_zone;
295 struct tm stm;
296 icaltime_t t;
297 struct icaltimetype local_tt;
298
300
301 /* Return 0 if the time is the special null time or a bad time */
303 return 0;
304 }
305
306 local_tt = tt;
307
308 /* Clear the is_date flag, so we can convert the time. */
309 local_tt.is_date = 0;
310
311 /* Use our timezone functions to convert to UTC. */
312 if (tt.zone != utc_zone) {
313 icaltimezone_convert_time(&local_tt, (icaltimezone *)zone, utc_zone);
314 }
315
316 /* Copy the icaltimetype to a struct tm. */
317 memset(&stm, 0, sizeof(struct tm));
318
319 stm.tm_sec = local_tt.second;
320 stm.tm_min = local_tt.minute;
321 stm.tm_hour = local_tt.hour;
322 stm.tm_mday = local_tt.day;
323 stm.tm_mon = local_tt.month - 1;
324 stm.tm_year = local_tt.year - 1900;
325 stm.tm_isdst = -1;
326
327 t = icaltime_timegm(&stm);
328
329 return t;
330}
331
332const char *icaltime_as_ical_string(const struct icaltimetype tt)
333{
334 char *buf;
335
338 return buf;
339}
340
342{
343 size_t size = 17;
344 char *buf = icalmemory_new_buffer(size);
345
346 if (tt.is_date) {
347 snprintf(buf, size, "%04d%02d%02d", tt.year, tt.month, tt.day);
348 } else {
349#pragma GCC diagnostic push
350#pragma GCC diagnostic ignored "-Wformat-nonliteral"
351 const char *fmt;
352
353 if (icaltime_is_utc(tt)) {
354 fmt = "%04d%02d%02dT%02d%02d%02dZ";
355 } else {
356 fmt = "%04d%02d%02dT%02d%02d%02d";
357 }
358 snprintf(buf, size, fmt, tt.year, tt.month, tt.day, tt.hour, tt.minute, tt.second);
359#pragma GCC diagnostic pop
360 }
361
362 return buf;
363}
364
365/* Implementation note: we call icaltime_adjust() with no adjustment. */
367{
368 struct icaltimetype ret = tt;
369
370 icaltime_adjust(&ret, 0, 0, 0, 0);
371 return ret;
372}
373
374struct icaltimetype icaltime_from_string(const char *str)
375{
376 struct icaltimetype tt = icaltime_null_time();
377 size_t size;
378
379 icalerror_check_arg_re(str != 0, "str", icaltime_null_time());
380
381 size = strlen(str);
382
383 if ((size == 15) || (size == 19)) { /* floating time with/without separators */
384 tt.is_date = 0;
385 } else if ((size == 16) || (size == 20)) { /* UTC time, ends in 'Z' */
386 if ((str[size - 1] != 'Z')) {
387 goto FAIL;
388 }
389
391 tt.is_date = 0;
392 } else if ((size == 8) || (size == 10)) { /* A DATE */
393 tt.is_date = 1;
394 } else { /* error */
395 goto FAIL;
396 }
397
398 if (tt.is_date == 1) {
399 if (size == 10) {
400 char dsep1, dsep2;
401
402 if (sscanf(str, "%04d%c%02d%c%02d",
403 &tt.year, &dsep1, &tt.month, &dsep2, &tt.day) < 5) {
404 goto FAIL;
405 }
406
407 if ((dsep1 != '-') || (dsep2 != '-')) {
408 goto FAIL;
409 }
410 } else if (sscanf(str, "%04d%02d%02d", &tt.year, &tt.month, &tt.day) < 3) {
411 goto FAIL;
412 }
413 } else {
414 if (size > 16) {
415 char dsep1, dsep2, tsep, tsep1, tsep2;
416
417 if (sscanf(str, "%04d%c%02d%c%02d%c%02d%c%02d%c%02d",
418 &tt.year, &dsep1, &tt.month, &dsep2, &tt.day, &tsep,
419 &tt.hour, &tsep1, &tt.minute, &tsep2, &tt.second) < 11) {
420 goto FAIL;
421 }
422
423 if ((tsep != 'T') ||
424 (dsep1 != '-') || (dsep2 != '-') ||
425 (tsep1 != ':') || (tsep2 != ':')) {
426 goto FAIL;
427 }
428
429 } else {
430 char tsep;
431
432 if (sscanf(str, "%04d%02d%02d%c%02d%02d%02d",
433 &tt.year, &tt.month, &tt.day, &tsep,
434 &tt.hour, &tt.minute, &tt.second) < 7) {
435 goto FAIL;
436 }
437
438 if (tsep != 'T') {
439 goto FAIL;
440 }
441 }
442 }
443
444 return tt;
445
446FAIL:
448 return icaltime_null_time();
449}
450
452{
453 if (year <= 1752) {
454 return (year % 4 == 0);
455 } else {
456 return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
457 }
458}
459
461{
463 return 366;
464 } else {
465 return 365;
466 }
467}
468
469static const int _days_in_month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
470
471int icaltime_days_in_month(const int month, const int year)
472{
473 int days;
474
475 /* The old code aborting if it was passed a parameter like BYMONTH=0
476 * Unfortunately it's not practical right now to pass an error all
477 * the way up the stack, so instead of aborting we're going to apply
478 * the GIGO principle and simply return '30 days' if we get an
479 * invalid month. Modern applications cannot tolerate crashing.
480 * assert(month > 0);
481 * assert(month <= 12);
482 */
483 if ((month < 1) || (month > 12)) {
484 return 30;
485 }
486
487 days = _days_in_month[month];
488
489 if (month == 2) {
490 days += (icaltime_is_leap_year(year) ? 1 : 0);
491 }
492
493 return days;
494}
495
496/* 1-> Sunday, 7->Saturday */
498{
499 UTinstantInt jt;
500
501 memset(&jt, 0, sizeof(UTinstantInt));
502
503 jt.year = t.year;
504 jt.month = t.month;
505 jt.day = t.day;
506
507 ical_juldat(&jt);
508
509 return jt.weekday + 1;
510}
511
512int icaltime_start_doy_week(const struct icaltimetype t, int fdow)
513{
514 UTinstantInt jt;
515 int delta;
516
517 memset(&jt, 0, sizeof(UTinstantInt));
518
519 jt.year = t.year;
520 jt.month = t.month;
521 jt.day = t.day;
522
523 ical_juldat(&jt);
524 ical_caldat(&jt);
525
526 delta = jt.weekday - (fdow - 1);
527 if (delta < 0) {
528 delta += 7;
529 }
530 return jt.day_of_year - delta;
531}
532
534{
535 unsigned int is_leap = (icaltime_is_leap_year(t.year) ? 1 : 0);
536
537 if (t.month < 1 || t.month > 12) {
538 return 0;
539 }
540
541 return days_in_year_passed_month[is_leap][t.month - 1] + t.day;
542}
543
544struct icaltimetype icaltime_from_day_of_year(const int _doy, const int _year)
545{
546 struct icaltimetype tt = icaltime_null_date();
547 unsigned int is_leap;
548 int month;
549 int doy = _doy;
550 int year = _year;
551
552 is_leap = (icaltime_is_leap_year(year) ? 1 : 0);
553
554 /* Zero and neg numbers represent days of the previous year */
555 if (doy < 1) {
556 year--;
557 is_leap = (icaltime_is_leap_year(year) ? 1 : 0);
558 doy += days_in_year_passed_month[is_leap][12];
559 } else if (doy > days_in_year_passed_month[is_leap][12]) {
560 /* Move on to the next year */
561 is_leap = (icaltime_is_leap_year(year) ? 1 : 0);
562 doy -= days_in_year_passed_month[is_leap][12];
563 year++;
564 }
565
566 tt.year = year;
567
568 for (month = 11; month >= 0; month--) {
569 if (doy > days_in_year_passed_month[is_leap][month]) {
570 tt.month = month + 1;
571 tt.day = doy - days_in_year_passed_month[is_leap][month];
572 break;
573 }
574 }
575
576 return tt;
577}
578
580{
581 struct icaltimetype t;
582
583 memset(&t, 0, sizeof(struct icaltimetype));
584
585 return t;
586}
587
589{
590 struct icaltimetype t;
591
592 memset(&t, 0, sizeof(struct icaltimetype));
593
594 t.is_date = 1;
595
596 /*
597 * Init to -1 to match what icalyacc.y used to do.
598 * Does anything depend on this?
599 */
600 t.hour = -1;
601 t.minute = -1;
602 t.second = -1;
603
604 return t;
605}
606
608{
609 // Note that we allow year, month and day to be zero to support null times
610 if (t.year < 0 || t.year > 9999 ||
611 t.month < 0 || t.month > 12 ||
612 t.day < 0 || t.day > 31 ||
613 t.is_date > 1 || t.is_date < 0) {
614 return false;
615 } else {
616 return true;
617 }
618}
619
620bool icaltime_is_date(const struct icaltimetype t)
621{
622 return (t.is_date != 0);
623}
624
625bool icaltime_is_utc(const struct icaltimetype t)
626{
628}
629
631{
632 if (t.second + t.minute + t.hour + t.day + t.month + t.year == 0) {
633 return true;
634 }
635
636 return false;
637}
638
639int icaltime_compare(const struct icaltimetype a_in, const struct icaltimetype b_in)
640{
641 struct icaltimetype a, b;
642
643 /* Ensure valid icaltimetypes, else the comparisons below mean nothing at all */
644 const bool a_is_valid = icaltime_is_valid_time(a_in);
645 const bool b_is_valid = icaltime_is_valid_time(b_in);
646 if (a_is_valid && !b_is_valid) {
647 return 1;
648 }
649 if (!a_is_valid) {
650 if (b_is_valid) {
651 return -1;
652 } else {
653 return 0;
654 }
655 }
656
657 /* We only need to perform time zone conversion if times aren't in the same time zone
658 or neither of them is floating (zone equals NULL) */
659 if (a_in.zone != b_in.zone && a_in.zone != NULL && b_in.zone != NULL) {
662 } else {
663 a = a_in;
664 b = b_in;
665 }
666
667 if (a.year > b.year) {
668 return 1;
669 } else if (a.year < b.year) {
670 return -1;
671 } else if (a.month > b.month) {
672 return 1;
673 } else if (a.month < b.month) {
674 return -1;
675 } else if (a.day > b.day) {
676 return 1;
677 } else if (a.day < b.day) {
678 return -1;
679 }
680
681 /* if both are dates, we are done */
682 if (a.is_date && b.is_date) {
683 return 0;
684
685 /* else, if only one is a date (and we already know the date part is equal),
686 then the other is greater */
687 } else if (b.is_date) {
688 return 1;
689 } else if (a.is_date) {
690 return -1;
691 } else if (a.hour > b.hour) {
692 return 1;
693 } else if (a.hour < b.hour) {
694 return -1;
695 } else if (a.minute > b.minute) {
696 return 1;
697 } else if (a.minute < b.minute) {
698 return -1;
699 } else if (a.second > b.second) {
700 return 1;
701 } else if (a.second < b.second) {
702 return -1;
703 }
704
705 return 0;
706}
707
709 const struct icaltimetype b_in)
710{
711 icaltimezone *tz;
712
713 /* prefer timezone of one of the times, because the UTC can change days in some cases */
714 if (a_in.zone != NULL) {
715 tz = (icaltimezone *)a_in.zone;
716 } else if (b_in.zone != NULL) {
717 tz = (icaltimezone *)b_in.zone;
718 } else {
720 }
721
722 return icaltime_compare_date_only_tz(a_in, b_in, tz);
723}
724
726 const struct icaltimetype b_in,
727 icaltimezone *tz)
728{
729 struct icaltimetype a, b;
730
731 a = icaltime_convert_to_zone(a_in, tz);
732 b = icaltime_convert_to_zone(b_in, tz);
733
734 if (a.year > b.year) {
735 return 1;
736 } else if (a.year < b.year) {
737 return -1;
738 }
739
740 if (a.month > b.month) {
741 return 1;
742 } else if (a.month < b.month) {
743 return -1;
744 }
745
746 if (a.day > b.day) {
747 return 1;
748 } else if (a.day < b.day) {
749 return -1;
750 }
751
752 return 0;
753}
754
756 const int days, const int hours,
757 const int minutes, const int seconds)
758{
759 int second, minute, hour, day;
760 int minutes_overflow, hours_overflow, days_overflow = 0, years_overflow;
761 int days_in_month;
762
763 if (icaltime_is_null_time(*tt)) { // do not attempt to adjust null times
764 return;
765 }
766
767 /* If we are passed a date make sure to ignore hour minute and second */
768 if (tt->is_date) {
769 goto IS_DATE;
770 }
771
772 /* Add on the seconds. */
773 second = tt->second + seconds;
774 tt->second = second % 60;
775 minutes_overflow = second / 60;
776 if (tt->second < 0) {
777 tt->second += 60;
778 minutes_overflow--;
779 }
780
781 /* Add on the minutes. */
782 minute = tt->minute + minutes + minutes_overflow;
783 tt->minute = minute % 60;
784 hours_overflow = minute / 60;
785 if (tt->minute < 0) {
786 tt->minute += 60;
787 hours_overflow--;
788 }
789
790 /* Add on the hours. */
791 hour = tt->hour + hours + hours_overflow;
792 tt->hour = hour % 24;
793 days_overflow = hour / 24;
794 if (tt->hour < 0) {
795 tt->hour += 24;
796 days_overflow--;
797 }
798
799IS_DATE:
800 /* Normalize the month. We do this before handling the day since we may
801 need to know what month it is to get the number of days in it.
802 Note that months are 1 to 12, so we have to be a bit careful. */
803 if (tt->month >= 13) {
804 years_overflow = (tt->month - 1) / 12;
805 tt->year += years_overflow;
806 tt->month -= years_overflow * 12;
807 } else if (tt->month <= 0) {
808 /* 0 to -11 is -1 year out, -12 to -23 is -2 years. */
809 years_overflow = (tt->month / 12) - 1;
810 tt->year += years_overflow;
811 tt->month -= years_overflow * 12;
812 }
813
814 /* Add on the days. */
815 day = tt->day + days + days_overflow;
816 if (day > 0) {
817 for (;;) {
818 days_in_month = icaltime_days_in_month(tt->month, tt->year);
819 if (day <= days_in_month) {
820 break;
821 }
822
823 tt->month++;
824 if (tt->month >= 13) {
825 tt->year++;
826 tt->month = 1;
827 }
828
829 day -= days_in_month;
830 }
831 } else {
832 while (day <= 0) {
833 if (tt->month == 1) {
834 tt->year--;
835 tt->month = 12;
836 } else {
837 tt->month--;
838 }
839
841 }
842 }
843 tt->day = day;
844}
845
847{
848 struct icaltimetype ret = tt;
849
850 /* If it's a date do nothing */
851 if (tt.is_date) {
852 return ret;
853 }
854
855 if (tt.zone == zone) {
856 return ret;
857 }
858
859 /* If it's a floating time we don't want to adjust the time */
860 if (tt.zone != NULL) {
862 }
863
864 ret.zone = zone;
865
866 return ret;
867}
868
870{
871 return t.zone;
872}
873
874const char *icaltime_get_tzid(const struct icaltimetype t)
875{
876 if (t.zone != NULL) {
878 } else {
879 return NULL;
880 }
881}
882
884{
885 /* If it's a date do nothing */
886 if (t->is_date) {
887 return *t;
888 }
889
890 if (t->zone == zone) {
891 return *t;
892 }
893
894 t->zone = zone;
895
896 return *t;
897}
void icalerror_set_errno(icalerrorenum x)
Sets the icalerrno to a given error.
Definition icalerror.c:90
Error handling for libical.
@ ICAL_MALFORMEDDATA_ERROR
Definition icalerror.h:59
void * icalmemory_new_buffer(size_t size)
Creates new buffer with the specified size.
Definition icalmemory.c:315
void icalmemory_add_tmp_buffer(void *buf)
Adds an externally allocated buffer to the ring.
Definition icalmemory.c:158
Common memory management routines.
struct icaltimetype icaltime_from_timet_with_zone(const icaltime_t tm, const bool is_date, const icaltimezone *zone)
Constructor.
Definition icaltime.c:209
bool icaltime_is_date(const struct icaltimetype t)
Definition icaltime.c:620
struct icaltimetype icaltime_from_string(const char *str)
Definition icaltime.c:374
const char * icaltime_get_tzid(const struct icaltimetype t)
Definition icaltime.c:874
struct icaltimetype icaltime_current_time_with_zone(const icaltimezone *zone)
Definition icaltime.c:249
int icaltime_day_of_year(const struct icaltimetype t)
Definition icaltime.c:533
int icaltime_start_doy_week(const struct icaltimetype t, int fdow)
Definition icaltime.c:512
bool icaltime_is_leap_year(const int year)
Definition icaltime.c:451
const icaltimezone * icaltime_get_timezone(const struct icaltimetype t)
Definition icaltime.c:869
int icaltime_day_of_week(const struct icaltimetype t)
Definition icaltime.c:497
struct icaltimetype icaltime_from_day_of_year(const int _doy, const int _year)
Definition icaltime.c:544
struct icaltimetype icaltime_today(void)
Convenience constructor.
Definition icaltime.c:254
struct icaltimetype icaltime_null_date(void)
Definition icaltime.c:588
bool icaltime_is_valid_time(const struct icaltimetype t)
Definition icaltime.c:607
const char * icaltime_as_ical_string(const struct icaltimetype tt)
Definition icaltime.c:332
int icaltime_days_in_month(const int month, const int year)
Definition icaltime.c:471
bool icaltime_is_utc(const struct icaltimetype t)
Definition icaltime.c:625
struct icaltimetype icaltime_convert_to_zone(const struct icaltimetype tt, icaltimezone *zone)
Definition icaltime.c:846
int icaltime_compare_date_only(const struct icaltimetype a_in, const struct icaltimetype b_in)
Definition icaltime.c:708
int icaltime_days_in_year(const int year)
Definition icaltime.c:460
bool icaltime_is_null_time(const struct icaltimetype t)
Definition icaltime.c:630
icaltime_t icaltime_as_timet_with_zone(const struct icaltimetype tt, const icaltimezone *zone)
Definition icaltime.c:292
struct icaltimetype icaltime_normalize(const struct icaltimetype tt)
Definition icaltime.c:366
icaltime_t icaltime_as_timet(const struct icaltimetype tt)
Definition icaltime.c:259
int icaltime_compare(const struct icaltimetype a_in, const struct icaltimetype b_in)
Definition icaltime.c:639
struct icaltimetype icaltime_set_timezone(struct icaltimetype *t, const icaltimezone *zone)
Definition icaltime.c:883
void icaltime_adjust(struct icaltimetype *tt, const int days, const int hours, const int minutes, const int seconds)
Definition icaltime.c:755
struct icaltimetype icaltime_null_time(void)
Definition icaltime.c:579
int icaltime_compare_date_only_tz(const struct icaltimetype a_in, const struct icaltimetype b_in, icaltimezone *tz)
Definition icaltime.c:725
char * icaltime_as_ical_string_r(const struct icaltimetype tt)
Definition icaltime.c:341
Defines the data structure for representing date-times.
struct icaltimetype icaltime_from_timet_with_zone(const icaltime_t tm, const bool is_date, const icaltimezone *zone)
Constructor.
Definition icaltime.c:209
bool icaltime_is_leap_year(const int year)
Definition icaltime.c:451
struct icaltimetype icaltime_null_date(void)
Definition icaltime.c:588
void icaltime_adjust(struct icaltimetype *tt, const int days, const int hours, const int minutes, const int seconds)
Definition icaltime.c:755
const char * icaltimezone_get_tzid(icaltimezone *zone)
icaltimezone * icaltimezone_get_utc_timezone(void)
void icaltimezone_convert_time(struct icaltimetype *tt, icaltimezone *from_zone, icaltimezone *to_zone)
Timezone handling routines.
struct _icaltimezone icaltimezone
int is_daylight
Definition icaltime.h:100
const icaltimezone * zone
Definition icaltime.h:102