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 /* 32-bit time_t cannot represent any instant after
108 2038-01-19T03:14:07 UTC (INT32_MAX seconds since the epoch). */
109 if (tm->tm_year == 138 &&
110 (tm->tm_mon > 0 ||
111 tm->tm_mday > 19 ||
112 (tm->tm_mday == 19 &&
113 (tm->tm_hour > 3 ||
114 (tm->tm_hour == 3 &&
115 (tm->tm_min > 14 ||
116 (tm->tm_min == 14 && tm->tm_sec > 7))))))) {
117 return false;
118 }
119
120#else
121 /* We don't support years >= 10000, because the function has not been tested at this range. */
122 if (tm->tm_year >= 8100) {
123 return false;
124 }
125#endif /* SIZEOF_ICALTIME_T */
126
127 /*
128 * calculate elapsed days since start of the epoch (midnight Jan
129 * 1st, 1970 UTC) 17 = number of leap years between 1900 and 1970
130 * (number of leap days to subtract)
131 */
132
133 tim = (icaltime_t)((tm->tm_year - 70) * 365 + ((tm->tm_year - 1) / 4) - 17);
134
135 /* adjust: no leap days every 100 years, except every 400 years. */
136
137 febs = (tm->tm_year - 100) - ((tm->tm_mon <= 1) ? 1 : 0);
138 tim -= febs / 100;
139 tim += febs / 400;
140
141 /* add number of days elapsed in the current year */
142
143 tim += days[tm->tm_mon];
144
145 /* check and adjust for leap years */
146
147 if ((tm->tm_year & 3) == 0 && tm->tm_mon > 1) {
148 tim += 1;
149 }
150
151 /* elapsed days to current date */
152
153 tim += tm->tm_mday;
154
155 /* calculate elapsed hours since start of the epoch */
156
157 tim = tim * 24 + tm->tm_hour;
158
159 /* calculate elapsed minutes since start of the epoch */
160
161 tim = tim * 60 + tm->tm_min;
162
163 /* adjust per time zone specification */
164
165 tim -= tzm;
166
167 /* calculate elapsed seconds since start of the epoch */
168
169 tim = tim * 60 + tm->tm_sec;
170
171 /* return number of seconds since start of the epoch */
172
173 if (out_time_t) {
174 *out_time_t = tim;
175 }
176
177 return true;
178}
179
180/*
181 * Code adapted from Python 2.4.1 sources (Lib/calendar.py).
182 */
183static icaltime_t icaltime_timegm(const struct tm *tm)
184{
185 int year;
186 icaltime_t days;
187 icaltime_t hours;
188 icaltime_t minutes;
189 icaltime_t seconds;
190
191 /* Validate the tm structure by passing it through make_time() */
192 if (!make_time(tm, 0, NULL)) {
193 /* we have some invalid data in the tm struct */
194 return 0;
195 }
196
197 year = 1900 + tm->tm_year;
198 int idays = (365 * (year - 1970) + icaltime_leap_days(1970, year));
199 days = (icaltime_t)idays;
200 days += days_in_year_passed_month[0][tm->tm_mon];
201
202 if (tm->tm_mon > 1 && icaltime_is_leap_year(year)) {
203 ++days;
204 }
205
206 days += tm->tm_mday - 1;
207 hours = days * 24 + tm->tm_hour;
208 minutes = hours * 60 + tm->tm_min;
209 seconds = minutes * 60 + tm->tm_sec;
210
211 return seconds;
212}
213
214struct icaltimetype icaltime_from_timet_with_zone(const icaltime_t tm, const bool is_date,
215 const icaltimezone *zone)
216{
217 struct icaltimetype tt;
218 struct tm t;
219 icaltimezone *utc_zone;
220
222
223 /* Convert the icaltime_t to a struct tm in UTC time. We can trust gmtime for this. */
224 memset(&t, 0, sizeof(struct tm));
225 if (!icalgmtime_r(&tm, &t)) {
226 return is_date ? icaltime_null_date() : icaltime_null_time();
227 }
228
229 tt.year = t.tm_year + 1900;
230 tt.month = t.tm_mon + 1;
231 tt.day = t.tm_mday;
232 tt.hour = t.tm_hour;
233 tt.minute = t.tm_min;
234 tt.second = t.tm_sec;
235 tt.is_date = 0;
236 tt.is_daylight = 0;
237 tt.zone = (zone == NULL) ? NULL : utc_zone;
238
239 /* Use our timezone functions to convert to the required timezone. */
240 icaltimezone_convert_time(&tt, utc_zone, (icaltimezone *)zone);
241
242 tt.is_date = is_date;
243
244 /* If it is a DATE value, make sure hour, minute & second are 0. */
245 if (is_date) {
246 tt.hour = 0;
247 tt.minute = 0;
248 tt.second = 0;
249 }
250
251 return tt;
252}
253
258
260{
261 return icaltime_from_timet_with_zone(icaltime(NULL), 1, NULL);
262}
263
264icaltime_t icaltime_as_timet(const struct icaltimetype tt)
265{
266 struct tm stm;
267 icaltime_t t = (icaltime_t)-1;
268
269 /* If the time is the special null time, return 0. */
270 if (icaltime_is_null_time(tt)) {
271 return 0;
272 }
273
274 /* Copy the icaltimetype to a struct tm. */
275 memset(&stm, 0, sizeof(struct tm));
276
277 if (icaltime_is_date(tt)) {
278 stm.tm_sec = stm.tm_min = stm.tm_hour = 0;
279 } else {
280 stm.tm_sec = tt.second;
281 stm.tm_min = tt.minute;
282 stm.tm_hour = tt.hour;
283 }
284
285 stm.tm_mday = tt.day;
286 stm.tm_mon = tt.month - 1;
287 stm.tm_year = tt.year - 1900;
288 stm.tm_isdst = -1;
289
290 if (!make_time(&stm, 0, &t)) {
291 t = ((icaltime_t)-1);
292 }
293
294 return t;
295}
296
297icaltime_t icaltime_as_timet_with_zone(const struct icaltimetype tt, const icaltimezone *zone)
298{
299 icaltimezone *utc_zone;
300 struct tm stm;
301 icaltime_t t;
302 struct icaltimetype local_tt;
303
305
306 /* Return 0 if the time is the special null time or a bad time */
308 return 0;
309 }
310
311 local_tt = tt;
312
313 /* Clear the is_date flag, so we can convert the time. */
314 local_tt.is_date = 0;
315
316 /* Use our timezone functions to convert to UTC. */
317 if (tt.zone != utc_zone) {
318 icaltimezone_convert_time(&local_tt, (icaltimezone *)zone, utc_zone);
319 }
320
321 /* Copy the icaltimetype to a struct tm. */
322 memset(&stm, 0, sizeof(struct tm));
323
324 stm.tm_sec = local_tt.second;
325 stm.tm_min = local_tt.minute;
326 stm.tm_hour = local_tt.hour;
327 stm.tm_mday = local_tt.day;
328 stm.tm_mon = local_tt.month - 1;
329 stm.tm_year = local_tt.year - 1900;
330 stm.tm_isdst = -1;
331
332 t = icaltime_timegm(&stm);
333
334 return t;
335}
336
337const char *icaltime_as_ical_string(const struct icaltimetype tt)
338{
339 char *buf;
340
343 return buf;
344}
345
347{
348 size_t size = 17;
349 char *buf = icalmemory_new_buffer(size);
350
351 if (tt.is_date) {
352 snprintf(buf, size, "%04d%02d%02d", tt.year, tt.month, tt.day);
353 } else {
354#pragma GCC diagnostic push
355#pragma GCC diagnostic ignored "-Wformat-nonliteral"
356 const char *fmt;
357
358 if (icaltime_is_utc(tt)) {
359 fmt = "%04d%02d%02dT%02d%02d%02dZ";
360 } else {
361 fmt = "%04d%02d%02dT%02d%02d%02d";
362 }
363 snprintf(buf, size, fmt, tt.year, tt.month, tt.day, tt.hour, tt.minute, tt.second);
364#pragma GCC diagnostic pop
365 }
366
367 return buf;
368}
369
370/* Implementation note: we call icaltime_adjust() with no adjustment. */
372{
373 struct icaltimetype ret = tt;
374
375 icaltime_adjust(&ret, 0, 0, 0, 0);
376 return ret;
377}
378
380{
381 struct icaltimetype tt = icaltime_null_time();
382 size_t size;
383
384 icalerror_check_arg_re(str != 0, "str", icaltime_null_time());
385
386 size = strlen(str);
387
388 if ((size == 15) || (size == 19)) { /* floating time with/without separators */
389 tt.is_date = 0;
390 } else if ((size == 16) || (size == 20)) { /* UTC time, ends in 'Z' */
391 if ((str[size - 1] != 'Z')) {
392 goto FAIL;
393 }
394
396 tt.is_date = 0;
397 } else if ((size == 8) || (size == 10)) { /* A DATE */
398 tt.is_date = 1;
399 } else { /* error */
400 goto FAIL;
401 }
402
403 if (tt.is_date == 1) {
404 if (size == 10) {
405 char dsep1, dsep2;
406
407 if (sscanf(str, "%04d%c%02d%c%02d",
408 &tt.year, &dsep1, &tt.month, &dsep2, &tt.day) < 5) {
409 goto FAIL;
410 }
411
412 if ((dsep1 != '-') || (dsep2 != '-')) {
413 goto FAIL;
414 }
415 } else if (sscanf(str, "%04d%02d%02d", &tt.year, &tt.month, &tt.day) < 3) {
416 goto FAIL;
417 }
418 } else {
419 if (size > 16) {
420 char dsep1, dsep2, tsep, tsep1, tsep2;
421
422 if (sscanf(str, "%04d%c%02d%c%02d%c%02d%c%02d%c%02d",
423 &tt.year, &dsep1, &tt.month, &dsep2, &tt.day, &tsep,
424 &tt.hour, &tsep1, &tt.minute, &tsep2, &tt.second) < 11) {
425 goto FAIL;
426 }
427
428 if ((tsep != 'T') ||
429 (dsep1 != '-') || (dsep2 != '-') ||
430 (tsep1 != ':') || (tsep2 != ':')) {
431 goto FAIL;
432 }
433
434 } else {
435 char tsep;
436
437 if (sscanf(str, "%04d%02d%02d%c%02d%02d%02d",
438 &tt.year, &tt.month, &tt.day, &tsep,
439 &tt.hour, &tt.minute, &tt.second) < 7) {
440 goto FAIL;
441 }
442
443 if (tsep != 'T') {
444 goto FAIL;
445 }
446 }
447 }
448
449 return tt;
450
451FAIL:
453 return icaltime_null_time();
454}
455
457{
458 if (year <= 1752) {
459 return (year % 4 == 0);
460 } else {
461 return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
462 }
463}
464
466{
468 return 366;
469 } else {
470 return 365;
471 }
472}
473
474static const int _days_in_month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
475
476int icaltime_days_in_month(const int month, const int year)
477{
478 int days;
479
480 /* The old code aborting if it was passed a parameter like BYMONTH=0
481 * Unfortunately it's not practical right now to pass an error all
482 * the way up the stack, so instead of aborting we're going to apply
483 * the GIGO principle and simply return '30 days' if we get an
484 * invalid month. Modern applications cannot tolerate crashing.
485 * assert(month > 0);
486 * assert(month <= 12);
487 */
488 if ((month < 1) || (month > 12)) {
489 return 30;
490 }
491
492 days = _days_in_month[month];
493
494 if (month == 2) {
495 days += (icaltime_is_leap_year(year) ? 1 : 0);
496 }
497
498 return days;
499}
500
501/* 1-> Sunday, 7->Saturday */
503{
504 UTinstantInt jt;
505
506 memset(&jt, 0, sizeof(UTinstantInt));
507
508 jt.year = t.year;
509 jt.month = t.month;
510 jt.day = t.day;
511
512 ical_juldat(&jt);
513
514 return jt.weekday + 1;
515}
516
517int icaltime_start_doy_week(const struct icaltimetype t, int fdow)
518{
519 UTinstantInt jt;
520 int delta;
521
522 memset(&jt, 0, sizeof(UTinstantInt));
523
524 jt.year = t.year;
525 jt.month = t.month;
526 jt.day = t.day;
527
528 ical_juldat(&jt);
529 ical_caldat(&jt);
530
531 delta = jt.weekday - (fdow - 1);
532 if (delta < 0) {
533 delta += 7;
534 }
535 return jt.day_of_year - delta;
536}
537
539{
540 unsigned int is_leap = (icaltime_is_leap_year(t.year) ? 1 : 0);
541
542 if (t.month < 1 || t.month > 12) {
543 return 0;
544 }
545
546 return days_in_year_passed_month[is_leap][t.month - 1] + t.day;
547}
548
549struct icaltimetype icaltime_from_day_of_year(const int _doy, const int _year)
550{
551 struct icaltimetype tt = icaltime_null_date();
552 unsigned int is_leap;
553 int month;
554 int doy = _doy;
555 int year = _year;
556
557 is_leap = (icaltime_is_leap_year(year) ? 1 : 0);
558
559 /* Zero and neg numbers represent days of the previous year */
560 if (doy < 1) {
561 year--;
562 is_leap = (icaltime_is_leap_year(year) ? 1 : 0);
563 doy += days_in_year_passed_month[is_leap][12];
564 } else if (doy > days_in_year_passed_month[is_leap][12]) {
565 /* Move on to the next year */
566 is_leap = (icaltime_is_leap_year(year) ? 1 : 0);
567 doy -= days_in_year_passed_month[is_leap][12];
568 year++;
569 }
570
571 tt.year = year;
572
573 for (month = 11; month >= 0; month--) {
574 if (doy > days_in_year_passed_month[is_leap][month]) {
575 tt.month = month + 1;
576 tt.day = doy - days_in_year_passed_month[is_leap][month];
577 break;
578 }
579 }
580
581 return tt;
582}
583
585{
586 struct icaltimetype t;
587
588 memset(&t, 0, sizeof(struct icaltimetype));
589
590 return t;
591}
592
594{
595 struct icaltimetype t;
596
597 memset(&t, 0, sizeof(struct icaltimetype));
598
599 t.is_date = 1;
600
601 /*
602 * Init to -1 to match what icalyacc.y used to do.
603 * Does anything depend on this?
604 */
605 t.hour = -1;
606 t.minute = -1;
607 t.second = -1;
608
609 return t;
610}
611
613{
614 // Note that we allow year, month and day to be zero to support null times
615 if (t.year < 0 || t.year > 9999 ||
616 t.month < 0 || t.month > 12 ||
617 t.day < 0 || t.day > 31 ||
618 t.is_date > 1 || t.is_date < 0) {
619 return false;
620 } else {
621 return true;
622 }
623}
624
625bool icaltime_is_date(const struct icaltimetype t)
626{
627 return (t.is_date != 0);
628}
629
630bool icaltime_is_utc(const struct icaltimetype t)
631{
633}
634
636{
637 if (t.second + t.minute + t.hour + t.day + t.month + t.year == 0) {
638 return true;
639 }
640
641 return false;
642}
643
644int icaltime_compare(const struct icaltimetype a_in, const struct icaltimetype b_in)
645{
646 struct icaltimetype a, b;
647
648 /* Ensure valid icaltimetypes, else the comparisons below mean nothing at all */
649 const bool a_is_valid = icaltime_is_valid_time(a_in);
650 const bool b_is_valid = icaltime_is_valid_time(b_in);
651 if (a_is_valid && !b_is_valid) {
652 return 1;
653 }
654 if (!a_is_valid) {
655 if (b_is_valid) {
656 return -1;
657 } else {
658 return 0;
659 }
660 }
661
662 /* We only need to perform time zone conversion if times aren't in the same time zone
663 or neither of them is floating (zone equals NULL) */
664 if (a_in.zone != b_in.zone && a_in.zone != NULL && b_in.zone != NULL) {
667 } else {
668 a = a_in;
669 b = b_in;
670 }
671
672 if (a.year > b.year) {
673 return 1;
674 } else if (a.year < b.year) {
675 return -1;
676 } else if (a.month > b.month) {
677 return 1;
678 } else if (a.month < b.month) {
679 return -1;
680 } else if (a.day > b.day) {
681 return 1;
682 } else if (a.day < b.day) {
683 return -1;
684 }
685
686 /* if both are dates, we are done */
687 if (a.is_date && b.is_date) {
688 return 0;
689
690 /* else, if only one is a date (and we already know the date part is equal),
691 then the other is greater */
692 } else if (b.is_date) {
693 return 1;
694 } else if (a.is_date) {
695 return -1;
696 } else if (a.hour > b.hour) {
697 return 1;
698 } else if (a.hour < b.hour) {
699 return -1;
700 } else if (a.minute > b.minute) {
701 return 1;
702 } else if (a.minute < b.minute) {
703 return -1;
704 } else if (a.second > b.second) {
705 return 1;
706 } else if (a.second < b.second) {
707 return -1;
708 }
709
710 return 0;
711}
712
714 const struct icaltimetype b_in)
715{
716 icaltimezone *tz;
717
718 /* prefer timezone of one of the times, because the UTC can change days in some cases */
719 if (a_in.zone != NULL) {
720 tz = (icaltimezone *)a_in.zone;
721 } else if (b_in.zone != NULL) {
722 tz = (icaltimezone *)b_in.zone;
723 } else {
725 }
726
727 return icaltime_compare_date_only_tz(a_in, b_in, tz);
728}
729
731 const struct icaltimetype b_in,
732 icaltimezone *tz)
733{
734 struct icaltimetype a, b;
735
736 a = icaltime_convert_to_zone(a_in, tz);
737 b = icaltime_convert_to_zone(b_in, tz);
738
739 if (a.year > b.year) {
740 return 1;
741 } else if (a.year < b.year) {
742 return -1;
743 }
744
745 if (a.month > b.month) {
746 return 1;
747 } else if (a.month < b.month) {
748 return -1;
749 }
750
751 if (a.day > b.day) {
752 return 1;
753 } else if (a.day < b.day) {
754 return -1;
755 }
756
757 return 0;
758}
759
761 const int days, const int hours,
762 const int minutes, const int seconds)
763{
764 int second, minute, hour, day;
765 int minutes_overflow, hours_overflow, days_overflow = 0, years_overflow;
766 int days_in_month;
767
768 if (icaltime_is_null_time(*tt)) { // do not attempt to adjust null times
769 return;
770 }
771
772 /* If we are passed a date make sure to ignore hour minute and second */
773 if (tt->is_date) {
774 goto IS_DATE;
775 }
776
777 /* Add on the seconds. */
778 second = tt->second + seconds;
779 tt->second = second % 60;
780 minutes_overflow = second / 60;
781 if (tt->second < 0) {
782 tt->second += 60;
783 minutes_overflow--;
784 }
785
786 /* Add on the minutes. */
787 minute = tt->minute + minutes + minutes_overflow;
788 tt->minute = minute % 60;
789 hours_overflow = minute / 60;
790 if (tt->minute < 0) {
791 tt->minute += 60;
792 hours_overflow--;
793 }
794
795 /* Add on the hours. */
796 hour = tt->hour + hours + hours_overflow;
797 tt->hour = hour % 24;
798 days_overflow = hour / 24;
799 if (tt->hour < 0) {
800 tt->hour += 24;
801 days_overflow--;
802 }
803
804IS_DATE:
805 /* Normalize the month. We do this before handling the day since we may
806 need to know what month it is to get the number of days in it.
807 Note that months are 1 to 12, so we have to be a bit careful. */
808 if (tt->month >= 13) {
809 years_overflow = (tt->month - 1) / 12;
810 tt->year += years_overflow;
811 tt->month -= years_overflow * 12;
812 } else if (tt->month <= 0) {
813 /* 0 to -11 is -1 year out, -12 to -23 is -2 years. */
814 years_overflow = (tt->month / 12) - 1;
815 tt->year += years_overflow;
816 tt->month -= years_overflow * 12;
817 }
818
819 /* Add on the days. */
820 day = tt->day + days + days_overflow;
821 if (day > 0) {
822 for (;;) {
823 days_in_month = icaltime_days_in_month(tt->month, tt->year);
824 if (day <= days_in_month) {
825 break;
826 }
827
828 tt->month++;
829 if (tt->month >= 13) {
830 tt->year++;
831 tt->month = 1;
832 }
833
834 day -= days_in_month;
835 }
836 } else {
837 while (day <= 0) {
838 if (tt->month == 1) {
839 tt->year--;
840 tt->month = 12;
841 } else {
842 tt->month--;
843 }
844
846 }
847 }
848 tt->day = day;
849}
850
852{
853 struct icaltimetype ret = tt;
854
855 /* If it's a date do nothing */
856 if (tt.is_date) {
857 return ret;
858 }
859
860 if (tt.zone == zone) {
861 return ret;
862 }
863
864 /* If it's a floating time we don't want to adjust the time */
865 if (tt.zone != NULL) {
867 }
868
869 ret.zone = zone;
870
871 return ret;
872}
873
875{
876 return t.zone;
877}
878
879const char *icaltime_get_tzid(const struct icaltimetype t)
880{
881 if (t.zone != NULL) {
883 } else {
884 return NULL;
885 }
886}
887
889{
890 /* If it's a date do nothing */
891 if (t->is_date) {
892 return *t;
893 }
894
895 if (t->zone == zone) {
896 return *t;
897 }
898
899 t->zone = zone;
900
901 return *t;
902}
const char * str
Definition icalenums.c:29
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:214
bool icaltime_is_date(const struct icaltimetype t)
Definition icaltime.c:625
struct icaltimetype icaltime_from_string(const char *str)
Definition icaltime.c:379
const char * icaltime_get_tzid(const struct icaltimetype t)
Definition icaltime.c:879
struct icaltimetype icaltime_current_time_with_zone(const icaltimezone *zone)
Definition icaltime.c:254
int icaltime_day_of_year(const struct icaltimetype t)
Definition icaltime.c:538
int icaltime_start_doy_week(const struct icaltimetype t, int fdow)
Definition icaltime.c:517
bool icaltime_is_leap_year(const int year)
Definition icaltime.c:456
const icaltimezone * icaltime_get_timezone(const struct icaltimetype t)
Definition icaltime.c:874
int icaltime_day_of_week(const struct icaltimetype t)
Definition icaltime.c:502
struct icaltimetype icaltime_from_day_of_year(const int _doy, const int _year)
Definition icaltime.c:549
struct icaltimetype icaltime_today(void)
Convenience constructor.
Definition icaltime.c:259
struct icaltimetype icaltime_null_date(void)
Definition icaltime.c:593
bool icaltime_is_valid_time(const struct icaltimetype t)
Definition icaltime.c:612
const char * icaltime_as_ical_string(const struct icaltimetype tt)
Definition icaltime.c:337
int icaltime_days_in_month(const int month, const int year)
Definition icaltime.c:476
bool icaltime_is_utc(const struct icaltimetype t)
Definition icaltime.c:630
struct icaltimetype icaltime_convert_to_zone(const struct icaltimetype tt, icaltimezone *zone)
Definition icaltime.c:851
int icaltime_compare_date_only(const struct icaltimetype a_in, const struct icaltimetype b_in)
Definition icaltime.c:713
int icaltime_days_in_year(const int year)
Definition icaltime.c:465
bool icaltime_is_null_time(const struct icaltimetype t)
Definition icaltime.c:635
icaltime_t icaltime_as_timet_with_zone(const struct icaltimetype tt, const icaltimezone *zone)
Definition icaltime.c:297
struct icaltimetype icaltime_normalize(const struct icaltimetype tt)
Definition icaltime.c:371
icaltime_t icaltime_as_timet(const struct icaltimetype tt)
Definition icaltime.c:264
int icaltime_compare(const struct icaltimetype a_in, const struct icaltimetype b_in)
Definition icaltime.c:644
struct icaltimetype icaltime_set_timezone(struct icaltimetype *t, const icaltimezone *zone)
Definition icaltime.c:888
void icaltime_adjust(struct icaltimetype *tt, const int days, const int hours, const int minutes, const int seconds)
Definition icaltime.c:760
struct icaltimetype icaltime_null_time(void)
Definition icaltime.c:584
int icaltime_compare_date_only_tz(const struct icaltimetype a_in, const struct icaltimetype b_in, icaltimezone *tz)
Definition icaltime.c:730
char * icaltime_as_ical_string_r(const struct icaltimetype tt)
Definition icaltime.c:346
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:214
bool icaltime_is_leap_year(const int year)
Definition icaltime.c:456
struct icaltimetype icaltime_null_date(void)
Definition icaltime.c:593
void icaltime_adjust(struct icaltimetype *tt, const int days, const int hours, const int minutes, const int seconds)
Definition icaltime.c:760
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