Add support for UTC times in iCal imports
According to the iCal standard (4.3.12 Time): UTC time, or absolute time, is identified by a LATIN CAPITAL LETTER Z suffix character (US-ASCII decimal 90), the UTC designator, appended to the time value. Parse such time values properly when importing iCal files. Fixes GitHub issue #3. Signed-off-by: Lukas Fleischer <calcurse@cryptocrack.de>
This commit is contained in:
parent
4efa3f3fbf
commit
1ea97795be
@ -1054,6 +1054,7 @@ long get_item_time(long);
|
|||||||
int get_item_hour(long);
|
int get_item_hour(long);
|
||||||
int get_item_min(long);
|
int get_item_min(long);
|
||||||
long date2sec(struct date, unsigned, unsigned);
|
long date2sec(struct date, unsigned, unsigned);
|
||||||
|
long utcdate2sec(struct date, unsigned, unsigned);
|
||||||
char *date_sec2date_str(long, const char *);
|
char *date_sec2date_str(long, const char *);
|
||||||
void date_sec2date_fmt(long, const char *, char *);
|
void date_sec2date_fmt(long, const char *, char *);
|
||||||
long date_sec_change(long, int, int);
|
long date_sec_change(long, int, int);
|
||||||
|
19
src/ical.c
19
src/ical.c
@ -477,7 +477,7 @@ ical_chk_header(FILE * fd, char *buf, char *lstore, unsigned *lineno,
|
|||||||
* where DATE is 'YYYYMMDD' and TIME is 'HHMMSS'.
|
* where DATE is 'YYYYMMDD' and TIME is 'HHMMSS'.
|
||||||
* The time and 'T' separator are optional (in the case of an day-long event).
|
* The time and 'T' separator are optional (in the case of an day-long event).
|
||||||
*
|
*
|
||||||
* Optionnaly, if the type pointer is given, specify if it is an event
|
* Optionally, if the type pointer is given, specify if it is an event
|
||||||
* (no time is given, meaning it is an all-day event), or an appointment
|
* (no time is given, meaning it is an all-day event), or an appointment
|
||||||
* (time is given).
|
* (time is given).
|
||||||
*
|
*
|
||||||
@ -485,21 +485,26 @@ ical_chk_header(FILE * fd, char *buf, char *lstore, unsigned *lineno,
|
|||||||
*/
|
*/
|
||||||
static long ical_datetime2long(char *datestr, ical_vevent_e * type)
|
static long ical_datetime2long(char *datestr, ical_vevent_e * type)
|
||||||
{
|
{
|
||||||
const int NOTFOUND = 0, FORMAT_DATE = 3, FORMAT_DATETIME = 5;
|
const int NOTFOUND = 0, FORMAT_DATE = 3, FORMAT_DATETIME = 6,
|
||||||
|
FORMAT_DATETIMEZ = 7;
|
||||||
struct date date;
|
struct date date;
|
||||||
unsigned hour, min;
|
unsigned hour, min, sec;
|
||||||
long datelong;
|
char c;
|
||||||
|
long datelong ;
|
||||||
int format;
|
int format;
|
||||||
|
|
||||||
format = sscanf(datestr, "%04u%02u%02uT%02u%02u",
|
format = sscanf(datestr, "%04u%02u%02uT%02u%02u%02u%c",
|
||||||
&date.yyyy, &date.mm, &date.dd, &hour, &min);
|
&date.yyyy, &date.mm, &date.dd, &hour, &min, &sec, &c);
|
||||||
if (format == FORMAT_DATE) {
|
if (format == FORMAT_DATE) {
|
||||||
if (type)
|
if (type)
|
||||||
*type = EVENT;
|
*type = EVENT;
|
||||||
datelong = date2sec(date, 0, 0);
|
datelong = date2sec(date, 0, 0);
|
||||||
} else if (format == FORMAT_DATETIME) {
|
} else if (format == FORMAT_DATETIME || format == FORMAT_DATETIMEZ) {
|
||||||
if (type)
|
if (type)
|
||||||
*type = APPOINTMENT;
|
*type = APPOINTMENT;
|
||||||
|
if (format == FORMAT_DATETIMEZ && c == 'Z')
|
||||||
|
datelong = utcdate2sec(date, hour, min);
|
||||||
|
else
|
||||||
datelong = date2sec(date, hour, min);
|
datelong = date2sec(date, hour, min);
|
||||||
} else {
|
} else {
|
||||||
datelong = NOTFOUND;
|
datelong = NOTFOUND;
|
||||||
|
25
src/utils.c
25
src/utils.c
@ -386,6 +386,31 @@ long date2sec(struct date day, unsigned hour, unsigned min)
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
time_t
|
||||||
|
utcdate2sec(struct date day, unsigned hour, unsigned min)
|
||||||
|
{
|
||||||
|
char *tz;
|
||||||
|
time_t t;
|
||||||
|
|
||||||
|
tz = getenv("TZ");
|
||||||
|
if (tz)
|
||||||
|
tz = mem_strdup(tz);
|
||||||
|
setenv("TZ", "", 1);
|
||||||
|
tzset();
|
||||||
|
|
||||||
|
t = date2sec(day, hour, min);
|
||||||
|
|
||||||
|
if (tz) {
|
||||||
|
setenv("TZ", tz, 1);
|
||||||
|
mem_free(tz);
|
||||||
|
} else {
|
||||||
|
unsetenv("TZ");
|
||||||
|
}
|
||||||
|
tzset();
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
/* Return a string containing the date, given a date in seconds. */
|
/* Return a string containing the date, given a date in seconds. */
|
||||||
char *date_sec2date_str(long sec, const char *datefmt)
|
char *date_sec2date_str(long sec, const char *datefmt)
|
||||||
{
|
{
|
||||||
|
@ -48,6 +48,7 @@ TESTS = \
|
|||||||
ical-004.sh \
|
ical-004.sh \
|
||||||
ical-005.sh \
|
ical-005.sh \
|
||||||
ical-006.sh \
|
ical-006.sh \
|
||||||
|
ical-007.sh \
|
||||||
next-001.sh \
|
next-001.sh \
|
||||||
search-001.sh \
|
search-001.sh \
|
||||||
bug-002.sh \
|
bug-002.sh \
|
||||||
@ -111,4 +112,5 @@ EXTRA_DIST = \
|
|||||||
data/ical-004.ical \
|
data/ical-004.ical \
|
||||||
data/ical-005.ical \
|
data/ical-005.ical \
|
||||||
data/ical-006.ical \
|
data/ical-006.ical \
|
||||||
|
data/ical-007.ical \
|
||||||
data/todo
|
data/todo
|
||||||
|
13
test/data/ical-007.ical
Normal file
13
test/data/ical-007.ical
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
BEGIN:VCALENDAR
|
||||||
|
VERSION:2.0
|
||||||
|
BEGIN:VEVENT
|
||||||
|
SUMMARY:Local time
|
||||||
|
DTSTART:20150223T110000
|
||||||
|
DURATION:PT1H
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
SUMMARY:UTC
|
||||||
|
DTSTART:20150223T110000Z
|
||||||
|
DURATION:PT1H
|
||||||
|
END:VEVENT
|
||||||
|
END:VCALENDAR
|
24
test/ical-007.sh
Executable file
24
test/ical-007.sh
Executable file
@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
. "${TEST_INIT:-./test-init.sh}"
|
||||||
|
|
||||||
|
if [ "$1" = 'actual' ]; then
|
||||||
|
mkdir .calcurse || exit 1
|
||||||
|
cp "$DATA_DIR/conf" .calcurse || exit 1
|
||||||
|
TZ="America/New_York" "$CALCURSE" -D "$PWD/.calcurse" \
|
||||||
|
-i "$DATA_DIR/ical-007.ical"
|
||||||
|
"$CALCURSE" -D "$PWD/.calcurse" -s2015-02-23
|
||||||
|
rm -rf .calcurse || exit 1
|
||||||
|
elif [ "$1" = 'expected' ]; then
|
||||||
|
cat <<EOD
|
||||||
|
Import process report: 0018 lines read
|
||||||
|
2 apps / 0 events / 0 todos / 0 skipped
|
||||||
|
02/23/15:
|
||||||
|
- 06:00 -> 07:00
|
||||||
|
UTC
|
||||||
|
- 11:00 -> 12:00
|
||||||
|
Local time
|
||||||
|
EOD
|
||||||
|
else
|
||||||
|
./run-test "$0"
|
||||||
|
fi
|
Loading…
x
Reference in New Issue
Block a user