Libical API Documentation 4.0 UNRELEASED Go to the stable 3.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 return days_in_year_passed_month[is_leap][t.month - 1] + t.day;
538}
539
540struct icaltimetype icaltime_from_day_of_year(const int _doy, const int _year)
541{
542 struct icaltimetype tt = icaltime_null_date();
543 unsigned int is_leap;
544 int month;
545 int doy = _doy;
546 int year = _year;
547
548 is_leap = (icaltime_is_leap_year(year) ? 1 : 0);
549
550 /* Zero and neg numbers represent days of the previous year */
551 if (doy < 1) {
552 year--;
553 is_leap = (icaltime_is_leap_year(year) ? 1 : 0);
554 doy += days_in_year_passed_month[is_leap][12];
555 } else if (doy > days_in_year_passed_month[is_leap][12]) {
556 /* Move on to the next year */
557 is_leap = (icaltime_is_leap_year(year) ? 1 : 0);
558 doy -= days_in_year_passed_month[is_leap][12];
559 year++;
560 }
561
562 tt.year = year;
563
564 for (month = 11; month >= 0; month--) {
565 if (doy > days_in_year_passed_month[is_leap][month]) {
566 tt.month = month + 1;
567 tt.day = doy - days_in_year_passed_month[is_leap][month];
568 break;
569 }
570 }
571
572 return tt;
573}
574
576{
577 struct icaltimetype t;
578
579 memset(&t, 0, sizeof(struct icaltimetype));
580
581 return t;
582}
583
585{
586 struct icaltimetype t;
587
588 memset(&t, 0, sizeof(struct icaltimetype));
589
590 t.is_date = 1;
591
592 /*
593 * Init to -1 to match what icalyacc.y used to do.
594 * Does anything depend on this?
595 */
596 t.hour = -1;
597 t.minute = -1;
598 t.second = -1;
599
600 return t;
601}
602
604{
605 // Note that we allow year, month and day to be zero to support null times
606 if (t.year < 0 || t.year > 9999 ||
607 t.month < 0 || t.month > 12 ||
608 t.day < 0 || t.day > 31 ||
609 t.is_date > 1 || t.is_date < 0) {
610 return false;
611 } else {
612 return true;
613 }
614}
615
616bool icaltime_is_date(const struct icaltimetype t)
617{
618 return (t.is_date != 0);
619}
620
621bool icaltime_is_utc(const struct icaltimetype t)
622{
624}
625
627{
628 if (t.second + t.minute + t.hour + t.day + t.month + t.year == 0) {
629 return true;
630 }
631
632 return false;
633}
634
635int icaltime_compare(const struct icaltimetype a_in, const struct icaltimetype b_in)
636{
637 struct icaltimetype a, b;
638
639 /* Ensure valid icaltimetypes, else the comparisons below mean nothing at all */
640 const bool a_is_valid = icaltime_is_valid_time(a_in);
641 const bool b_is_valid = icaltime_is_valid_time(b_in);
642 if (a_is_valid && !b_is_valid) {
643 return 1;
644 }
645 if (!a_is_valid) {
646 if (b_is_valid) {
647 return -1;
648 } else {
649 return 0;
650 }
651 }
652
653 /* We only need to perform time zone conversion if times aren't in the same time zone
654 or neither of them is floating (zone equals NULL) */
655 if (a_in.zone != b_in.zone && a_in.zone != NULL && b_in.zone != NULL) {
658 } else {
659 a = a_in;
660 b = b_in;
661 }
662
663 if (a.year > b.year) {
664 return 1;
665 } else if (a.year < b.year) {
666 return -1;
667 } else if (a.month > b.month) {
668 return 1;
669 } else if (a.month < b.month) {
670 return -1;
671 } else if (a.day > b.day) {
672 return 1;
673 } else if (a.day < b.day) {
674 return -1;
675 }
676
677 /* if both are dates, we are done */
678 if (a.is_date && b.is_date) {
679 return 0;
680
681 /* else, if only one is a date (and we already know the date part is equal),
682 then the other is greater */
683 } else if (b.is_date) {
684 return 1;
685 } else if (a.is_date) {
686 return -1;
687 } else if (a.hour > b.hour) {
688 return 1;
689 } else if (a.hour < b.hour) {
690 return -1;
691 } else if (a.minute > b.minute) {
692 return 1;
693 } else if (a.minute < b.minute) {
694 return -1;
695 } else if (a.second > b.second) {
696 return 1;
697 } else if (a.second < b.second) {
698 return -1;
699 }
700
701 return 0;
702}
703
705 const struct icaltimetype b_in)
706{
707 struct icaltimetype a, b;
709
710 a = icaltime_convert_to_zone(a_in, tz);
711 b = icaltime_convert_to_zone(b_in, tz);
712
713 if (a.year > b.year) {
714 return 1;
715 } else if (a.year < b.year) {
716 return -1;
717 }
718
719 if (a.month > b.month) {
720 return 1;
721 } else if (a.month < b.month) {
722 return -1;
723 }
724
725 if (a.day > b.day) {
726 return 1;
727 } else if (a.day < b.day) {
728 return -1;
729 }
730
731 return 0;
732}
733
735 const struct icaltimetype b_in,
736 icaltimezone *tz)
737{
738 struct icaltimetype a, b;
739
740 a = icaltime_convert_to_zone(a_in, tz);
741 b = icaltime_convert_to_zone(b_in, tz);
742
743 if (a.year > b.year) {
744 return 1;
745 } else if (a.year < b.year) {
746 return -1;
747 }
748
749 if (a.month > b.month) {
750 return 1;
751 } else if (a.month < b.month) {
752 return -1;
753 }
754
755 if (a.day > b.day) {
756 return 1;
757 } else if (a.day < b.day) {
758 return -1;
759 }
760
761 return 0;
762}
763
765 const int days, const int hours,
766 const int minutes, const int seconds)
767{
768 int second, minute, hour, day;
769 int minutes_overflow, hours_overflow, days_overflow = 0, years_overflow;
770 int days_in_month;
771
772 if (icaltime_is_null_time(*tt)) { // do not attempt to adjust null times
773 return;
774 }
775
776 /* If we are passed a date make sure to ignore hour minute and second */
777 if (tt->is_date) {
778 goto IS_DATE;
779 }
780
781 /* Add on the seconds. */
782 second = tt->second + seconds;
783 tt->second = second % 60;
784 minutes_overflow = second / 60;
785 if (tt->second < 0) {
786 tt->second += 60;
787 minutes_overflow--;
788 }
789
790 /* Add on the minutes. */
791 minute = tt->minute + minutes + minutes_overflow;
792 tt->minute = minute % 60;
793 hours_overflow = minute / 60;
794 if (tt->minute < 0) {
795 tt->minute += 60;
796 hours_overflow--;
797 }
798
799 /* Add on the hours. */
800 hour = tt->hour + hours + hours_overflow;
801 tt->hour = hour % 24;
802 days_overflow = hour / 24;
803 if (tt->hour < 0) {
804 tt->hour += 24;
805 days_overflow--;
806 }
807
808IS_DATE:
809 /* Normalize the month. We do this before handling the day since we may
810 need to know what month it is to get the number of days in it.
811 Note that months are 1 to 12, so we have to be a bit careful. */
812 if (tt->month >= 13) {
813 years_overflow = (tt->month - 1) / 12;
814 tt->year += years_overflow;
815 tt->month -= years_overflow * 12;
816 } else if (tt->month <= 0) {
817 /* 0 to -11 is -1 year out, -12 to -23 is -2 years. */
818 years_overflow = (tt->month / 12) - 1;
819 tt->year += years_overflow;
820 tt->month -= years_overflow * 12;
821 }
822
823 /* Add on the days. */
824 day = tt->day + days + days_overflow;
825 if (day > 0) {
826 for (;;) {
827 days_in_month = icaltime_days_in_month(tt->month, tt->year);
828 if (day <= days_in_month) {
829 break;
830 }
831
832 tt->month++;
833 if (tt->month >= 13) {
834 tt->year++;
835 tt->month = 1;
836 }
837
838 day -= days_in_month;
839 }
840 } else {
841 while (day <= 0) {
842 if (tt->month == 1) {
843 tt->year--;
844 tt->month = 12;
845 } else {
846 tt->month--;
847 }
848
850 }
851 }
852 tt->day = day;
853}
854
856{
857 struct icaltimetype ret = tt;
858
859 /* If it's a date do nothing */
860 if (tt.is_date) {
861 return ret;
862 }
863
864 if (tt.zone == zone) {
865 return ret;
866 }
867
868 /* If it's a floating time we don't want to adjust the time */
869 if (tt.zone != NULL) {
871 }
872
873 ret.zone = zone;
874
875 return ret;
876}
877
879{
880 return t.zone;
881}
882
883const char *icaltime_get_tzid(const struct icaltimetype t)
884{
885 if (t.zone != NULL) {
887 } else {
888 return NULL;
889 }
890}
891
893{
894 /* If it's a date do nothing */
895 if (t->is_date) {
896 return *t;
897 }
898
899 if (t->zone == zone) {
900 return *t;
901 }
902
903 t->zone = zone;
904
905 return *t;
906}
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:56
void * icalmemory_new_buffer(size_t size)
Creates new buffer with the specified size.
Definition icalmemory.c:313
void icalmemory_add_tmp_buffer(void *buf)
Adds an externally allocated buffer to the ring.
Definition icalmemory.c:156
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:616
struct icaltimetype icaltime_from_string(const char *str)
Definition icaltime.c:374
const char * icaltime_get_tzid(const struct icaltimetype t)
Definition icaltime.c:883
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:878
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:540
struct icaltimetype icaltime_today(void)
Convenience constructor.
Definition icaltime.c:254
struct icaltimetype icaltime_null_date(void)
Definition icaltime.c:584
bool icaltime_is_valid_time(const struct icaltimetype t)
Definition icaltime.c:603
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:621
struct icaltimetype icaltime_convert_to_zone(const struct icaltimetype tt, icaltimezone *zone)
Definition icaltime.c:855
int icaltime_compare_date_only(const struct icaltimetype a_in, const struct icaltimetype b_in)
Definition icaltime.c:704
int icaltime_days_in_year(const int year)
Definition icaltime.c:460
bool icaltime_is_null_time(const struct icaltimetype t)
Definition icaltime.c:626
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:635
struct icaltimetype icaltime_set_timezone(struct icaltimetype *t, const icaltimezone *zone)
Definition icaltime.c:892
void icaltime_adjust(struct icaltimetype *tt, const int days, const int hours, const int minutes, const int seconds)
Definition icaltime.c:764
struct icaltimetype icaltime_null_time(void)
Definition icaltime.c:575
int icaltime_compare_date_only_tz(const struct icaltimetype a_in, const struct icaltimetype b_in, icaltimezone *tz)
Definition icaltime.c:734
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:584
void icaltime_adjust(struct icaltimetype *tt, const int days, const int hours, const int minutes, const int seconds)
Definition icaltime.c:764
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