tics2tsv - ics2txt - convert icalendar .ics file to plain text | |
git clone git://bitreich.org/ics2txt git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws… | |
Log | |
Files | |
Refs | |
Tags | |
README | |
--- | |
tics2tsv (2949B) | |
--- | |
1 #!/usr/bin/awk -f | |
2 | |
3 function isleap(year) | |
4 { | |
5 return (year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0) | |
6 } | |
7 | |
8 function mdays(mon, year) | |
9 { | |
10 return (mon == 2) ? (28 + isleap(year)) : (30 + (mon + (mon > 7)… | |
11 } | |
12 | |
13 function timegm(tm, | |
14 sec, mon, day) | |
15 { | |
16 sec = tm["sec"] + tm["min"] * 60 + tm["hour"] * 3600 | |
17 | |
18 day = tm["mday"] - 1 | |
19 | |
20 for (mon = tm["mon"] - 1; mon > 0; mon--) | |
21 day = day + mdays(mon, tm["year"]) | |
22 | |
23 # constants: x * 365 + x / 400 - x / 100 + x / 4 | |
24 day = day + int(tm["year"] / 400) * 146097 | |
25 day = day + int(tm["year"] % 400 / 100) * 36524 | |
26 day = day + int(tm["year"] % 100 / 4) * 1461 | |
27 day = day + int(tm["year"] % 4 / 1) * 365 | |
28 | |
29 return sec + (day - 719527) * 86400 | |
30 } | |
31 | |
32 function print_vevent(ev, fields, | |
33 i) | |
34 { | |
35 for (i = 1; i in fields; i++) | |
36 printf("%s%s", (i > 1 ? "\t" : ""), ev[fields[i]]) | |
37 printf("\n") | |
38 } | |
39 | |
40 function ical_parse_line(str, content, params, | |
41 i, eq) | |
42 { | |
43 if ((i = index(str, ":")) == 0) | |
44 return -1 | |
45 content["value"] = substr(str, i + 1) | |
46 str = substr(str, 1, i - 1) | |
47 | |
48 if ((i = index(str, ";")) == 0) { | |
49 content["name"] = str | |
50 return 0 | |
51 } | |
52 content["name"] = substr(str, 1, i - 1) | |
53 str = substr(str, i + 1) | |
54 | |
55 while ((i = index(str, ";")) > 0) { | |
56 if ((eq = index(str, "=")) == 0) | |
57 return -1 | |
58 param[substr(str, 1, eq - 1)] = substr(str, eq + 1, i - … | |
59 str = substr(str, eq + 1) | |
60 } | |
61 if ((eq = index(str, "=")) == 0) | |
62 return -1 | |
63 params[substr(str, 1, eq - 1)] = substr(str, eq + 1) | |
64 return 0 | |
65 } | |
66 | |
67 function ical_set_tz(tzid) | |
68 { | |
69 gsub("'", "", tzid) | |
70 cmd = "TZ='" tzid "' exec date +%z" | |
71 cmd | getline tzid | |
72 close(cmd) | |
73 TZ = substr(tzid, 1, 1) substr(tzid, 2, 2)*3600 + substr(tzid, 4… | |
74 } | |
75 | |
76 function ical_to_epoch(content, param, | |
77 tz, cmd) | |
78 { | |
79 if (param["TZID"]) | |
80 ical_set_tz(param["TZID"]) | |
81 | |
82 tm["year"] = substr(content["value"], 1, 4) | |
83 tm["mon"] = substr(content["value"], 5, 2) | |
84 tm["mday"] = substr(content["value"], 7, 2) | |
85 tm["hour"] = substr(content["value"], 10, 2) | |
86 tm["min"] = substr(content["value"], 12, 2) | |
87 tm["sec"] = substr(content["value"], 14, 2) | |
88 | |
89 return timegm(tm) + TZ | |
90 } | |
91 | |
92 BEGIN { | |
93 split("DTSTART DTEND CATEGORIES LOCATION SUMMARY DESCRIPTION URL… | |
94 FIELDS, " ") | |
95 DT["DTSTART"] = DT["DTEND"] = DT["DUE"] = 1 | |
96 | |
97 # by default: "CATEGORIES" -> "cat", "LOCATION" -> "loc"... | |
98 translate["DTSTART"] = "beg" | |
99 translate["DTEND"] = "end" | |
100 | |
101 for (i = 1; i in FIELDS; i++) { | |
102 if (!(s = translate[FIELDS[i]])) | |
103 s = tolower(substr(FIELDS[i], 1, 3)) | |
104 printf("%s%s", (i > 1 ? "\t" : ""), s) | |
105 } | |
106 printf("\n") | |
107 | |
108 FS = "[:;]" | |
109 } | |
110 | |
111 { | |
112 gsub("\r", "") | |
113 gsub("\t", "\\\\t") | |
114 } | |
115 | |
116 sub("^ ", "") { | |
117 content["value"] = content["value"] $0 | |
118 next | |
119 } | |
120 | |
121 { | |
122 delete content | |
123 delete param | |
124 | |
125 if (ical_parse_line($0, content, params) < 0) | |
126 next | |
127 | |
128 if (content["name"] == "TZID") { | |
129 ical_set_tz(content["value"]) | |
130 } else if (DT[content["name"]]) { | |
131 vevent[content["name"]] = ical_to_epoch(content, params) | |
132 } else { | |
133 vevent[content["name"]] = content["value"] | |
134 } | |
135 } | |
136 | |
137 /^END:VEVENT/ { | |
138 print_vevent(vevent, FIELDS) | |
139 delete vevent | |
140 next | |
141 } |