I had submitted an awk script to convert .vcs or .ics appointments
into dtcm(1) appointments in the XAPIA format. This script is
distributed with CDE in the contrib/ directory. I have made some
improvements to the script to handle repeating appointments.
Since there is a CDE release in preparation, I am sending the new script
to the list.
I am also sending a script that creates appointments for (Roman
Catholic) Easter, Ascencion Day and Whit Sunday. It might also be
distributed with CDE in contrib/ under the terms of MIT license.
#/usr/bin/awk -f
# Edmond Orignac (c) 2016. This awk program
# attempts to convert .ics/.vcs files into XAPIA format for dtcm(1) appointment.
# It is redistributable under the terms of MIT License.
BEGIN {FS=":"}
/^BEGIN/ {if ($2~"VEVENT") {appnt=1; rxtype=0; nxr=0; mxday=0; mxmonth=0;
runtil=0; xinterval=0}
}
/^TZ/ {if ($2~"[+-][1-9]*") {timezone=$2} else {timezone=0}}
# Knowing the timezone, we can convert local time to UTC time.
/^DTSTART/ {sdate=$2}
/^DTEND/ {fdate=$2}
/^DESCRIPTION/ {summary=summary" "substr($0,13)}
/^SUMMARY/ {summary=summary" "substr($0,9)}
/^LOCATION/ {summary=summary" in "substr($0,10)}
/^RRULE/ {rrule=$2;
# The event will repeat forever unless we find a limit
nxr=0;
rfields=split(rrule,rdata,";");
for (i=1;i<=rfields;i++) {
if (rdata[i]~"FREQ") {
rtype=substr(rdata[i],5);
if (rtype~"DAILY") rxtype=1;
if (rtype~"WEEKLY") rxtype=2;
# We assume a monthly repeat by date for now
if (rtype~"MONTHLY") rxtype=5;
if (rtype~"YEARLY") rxtype=6;
}
if (rdata[i]~"COUNT") {nxr=substr(rdata[i],7)};
if (rdata[i]~"BYDAY") {
rdays=substr(rdata[i],7);
nrdays=split(rdata[i],ddays,",");
# nrdays=1: we have a simple monthly repeat by weekday
if ((nrdays==1) && (rxtype==5)) {rxtype=4};
# with nrdays > 1 we have a problem:
# XAPIA format only allows limited forms of weekly repeats
if ((nrdays>1) && (rxtype=2)) {
if (nrdays==2) {
tuth=match(ddays[1],"TU")+match(ddays[2],"TH");
if (tuth==2) {rxtype=12};
};
if (nrdays==3) {
mowefr=0;
for (j=1;j<=nrdays;j++) {
mowefr+=match(ddays[j],"MO");
mowefr+=match(ddays[j],"WE");
mowefr+=match(ddays[j],"FR");
};
if (mowefr==3) {rxtype=11};
};
if (nrdays==5) {
wweek=0;
for (j=1;j<=nrdays;j++) {
wweek+=match(ddays[j],"MO");
wweek+=match(ddays[j],"TU");
wweek+=match(ddays[j],"WE");
wweek+=match(ddays[j],"TH");
wweek+=match(ddays[j],"FR");
};
if (wweek==5) {rxtype=10};
};
};
};
# This is bad: if we have not found a repeat by day matching one XAPIA
# format, the repetition rule is not fully defined.
# Most likely we will have only one of the appointments of the week.
if (rdata[i]~"BYMONTHDAY=") {mxday=substr(rdata[i],12)};
if (rdata[i]~"BYMONTH=") {mxmonth=substr(rdata[i],9)};
if (rdata[i]~"INTERVAL=") {xinterval=substr(rdata[i],10)
# Weekly appointment with a 2 week interval is definec in XAPIA
if ((xinterval==2) && (rxtype==2)) {rxtype=3}
# Monthly appointment with a 12 month interval is really a yearly appointment
if ((xinterval==12) && (rxtype=5)) {rxtype=6}
# Weekly appointment with N>2 interval
if ((xinterval>2) && (rxtype==2)) {rxtype=8}
# Monthly appointment with N>=2 interval (12 month excluded)
if ((xinterval>=2) && (rxtype==5)) {rxtype=9}
# Daily appointment with N>=2 interval
if ((xinterval>=2) && (rxtype==1)) {rxtype=7}
};
# Repetition until a date in the future
if (rdata[i]~"UNTIL=") {xuntil=substr(rdata[i],7); runtil=1};
};
};
/^END/ {if ($2~"VEVENT") {
# # That one is annoying: we have to calculate the number of repetitions !
# We do that by using an average duration for the year and for the month
# but obviously this is imprecise, and the last appointment may not be there.
# Also, we must do it here since DTSTART can appear at the very end
# of an entry. The arithmetics gets sillier with repeat every n
week/day/month...
if (runtil==1) {
uyear=substr(xuntil,1,4)-substr(sdate,1,4);
umonth=substr(xuntil,5,2)-substr(sdate,5,2);
uday=substr(xuntil,7,2)-substr(sdate,7,2);
if (rxtype==1) nxr=int(365.25*uyear+30.44*umonth+uday)+1;
if (rxtype==2) nxr=int((365.25*uyear+30.44*umonth+uday)/7.0)+1;
if (rxtype==3) nxr=int((365.25*uyear+30.44*umonth+uday)/14.0)+1;
if ((rxtype==4)||(rxtype==5)) nxr=12*uyear+umonth+1;
if (rxtype==6) nxr=uyear+1;
if (rxtype==7)
nxr=int((365.25*uyear+30.44*umonth+uday)/xinterval)+1;
if (rxtype==8)
nxr=int((365.25*uyear+30.44*umonth+uday)/(7*xinterval))+1;
if (rxtype==9) nxr=int((12*uyear+umonth)/xinterval)+1;
if (rxtype==10)
nxr=int(5.0*(365.25*uyear+30.44*umonth+uday)/7.0)+1;
if (rxtype==11)
nxr=int(3.0*(365.25*uyear+30.44*umounth+uday)/7.0)+1;
if (rxtype==12)
nxr=int(3.0*(365.25*uyear+30.44*umounth+uday)/7.0)+1;
if (nxr<0) nxr=0;
};
# Another important thing is that dtcm does not like events that spread
# over more than 24 hours. So we have to find how many days is fdate-sdate
# and if that is more than 1 day transform the event into a daily repeat.
dyear=substr(fdate,1,4)-substr(sdate,1,4);
dmonth=substr(fdate,5,2)-substr(sdate,5,2);
dday=int(substr(fdate,7,2)-substr(sdate,7,2)+30.44*dmonth+365.25*dyear);
if ((rxtype==0) && (dday>0)) {rxtype=1;nxr=dday+1};
# Start hour and End hour have to be converted to UTC first if timezone is
defined.
printf("\n\n")
print "\t** Calendar Appointment **"
print "-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Entry
Delimiter//EN:string:begin";
printf("-//XAPIA/CSA/ENTRYATTR//NONSGML Start
Date//EN:datetime:%s\n",sdate);
print "-//XAPIA/CSA/ENTRYATTR//NONSGML Type//EN:uinteger:0";
print "-//XAPIA/CSA/ENTRYATTR//NONSGML
Subtype//EN:string:-//XAPIA/CSA/SUBTYPE//NONSGML Subtype Appointment//EN";
print "-//XAPIA/CSA/ENTRYATTR//NONSGML Classification//EN:uinteger:0";
if (rxtype==0) {
printf("-//XAPIA/CSA/ENTRYATTR//NONSGML End
Date//EN:datetime:%s\n",fdate);
} else {
qdate=substr(sdate,1,8) substr(fdate,9);
printf("-//XAPIA/CSA/ENTRYATTR//NONSGML End
Date//EN:datetime:%s\n",qdate);
};
print "-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Show
Time//EN:sinteger:1";
printf("-//XAPIA/CSA/ENTRYATTR//NONSGML
Summary//EN:string:%s\n",summary);
print "-//XAPIA/CSA/ENTRYATTR//NONSGML Status//EN:uinteger:2304";
printf("-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Repeat
Type//EN:sinteger:%d\n",rxtype);
printf("-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Repeat
Times//EN:uinteger:%d\n",nxr);
print "-//XAPIA/CSA/ENTRYATTR//NONSGML Audio
Reminder//EN:reminder:300:";
print "-//XAPIA/CSA/ENTRYATTR//NONSGML Popup
Reminder//EN:reminder:300:";
print "-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Repeat Occurrence
Number//EN:sinteger:-1";
printf("-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Repeat
Interval//EN:uinteger:%d\n",rinterval);
print "-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Entry
Delimiter//EN:string:end";
printf("\tDate:
%s/%s/%s\n",substr(sdate,5,2),substr(sdate,7,2),substr(sdate,1,4));
# The start/end time are in UTC and have to be converted to local time. We
assume the local time is UTC+1
shour=substr(sdate,10,2);
smin=substr(sdate,12,2);
fhour=substr(fdate,10,2);
fmin=substr(fdate,12,2);
if ((fhour+fmin+shour+smin)==0) {fhour=01;fmin=42;shour=01;smin=41}
shour++;
fhour++;
printf("\tStart: %.2d%.2d\n",shour,smin)
printf("\tEnd: %.2d%.2d\n",fhour,fmin)
if (rxtype==0) {print "\tRepeat: One Time"};
if (rxtype==1) {print "\tRepeat: Daily"};
if (rxtype==2) {print "\tRepeat: Weekly"};
if (rxtype==3) {print "\tRepeat: Every Two Weeks"};
if (rxtype==4) {print "\tRepeat: Monthly By Weekday"};
if (rxtype==5) {print "\tRepeat: Monthly By Date"};
if (rxtype==6) {print "\tRepeat: Yearly"}
if (rxtype==7) {printf("\t Repeat Every %d days\n",xinterval)}
if (rxtype==8) {printf("\t Repeat Every %d weeks\n",xinterval)}
if (rxtype==9) {printf("\t Repeat Every %d months\n",xinterval)}
if (rxtype==10) {print "\tRepeat: Monday thru Friday"};
if (rxtype==11) {print "\tRepeat: Mon, Wed, Fri"};
if (rxtype==12) {print "\tRepeat: Tuesday, Thursday"};
printf("\tFor: %d\n",nxr);
printf("\tWhat: %s\n",summary);
printf("\t\n");
sdate="";
fdate="";
appnt=0;
summary="";
}
}
BEGIN {
y=2016; # change to the appropriate year !
lang=ENVIRON["LANG"]
easter["C"]="Easter"
easter["fr_FR.ISO8859-1"]="Pâques"
easter["it_IT.ISO8859-1"]="Pasqua"
easter["es_ES.ISO8859-1"]="Pascua"
easter["de_DE.ISO8859-1"]="Ostersonntag"
ascension["C"]="Ascension Day"
ascension["fr_FR.ISO8859-1"]="Ascension"
ascension["it_IT.ISO8859-1"]="Ascensione"
ascension["es_ES.ISO8859-1"]="Ascension"
ascension["de_DE.ISO8859-1"]="Christi Himmelfahrt"
whit["C"]="Whit Sunday"
whit["fr_FR.ISO8859-1"]="Pentecôte"
whit["it_IT.ISO8859-1"]="Spirito Sancto"
whit["es_ES.ISO8859-1"]="Pentecostés"
whit["de_DE.ISO8859-1"]="Pfingstsonntag"
# Formula to calculate the date of Easter
g=y%19;
c=int(y/100);
c4=int(c/4);
e=int((8*c+13)/25);
h=(19*g+c-c4-e+15)%30;
k=int(h/28);
p=int(29/(h+1));
q=int((21-g)/11);
i=(k*p*q-1)*k+h;
b=int(y/4)+y;
j1=b+i+2+c4-c;
j2=j1%7;
r=28+i-j2;
m=int(r/32)+3;
d=r-31*(m-3);
# Creating an appointment in XAPIA format for Easter
sdate=sprintf("%.4d%.2d%.2dT004100Z",d,m,y);
fdate=sprintf("%.4d%.2d%.2dT004200Z",d,m,y);
appt="easter_"y;
printf("\n\n") >appt
print "\t** Calendar Appointment **" >appt
print "-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Entry
Delimiter//EN:string:begin">appt;
printf("-//XAPIA/CSA/ENTRYATTR//NONSGML Start
Date//EN:datetime:%s\n",sdate)>appt;
print "-//XAPIA/CSA/ENTRYATTR//NONSGML Type//EN:uinteger:0">appt;
print "-//XAPIA/CSA/ENTRYATTR//NONSGML
Subtype//EN:string:-//XAPIA/CSA/SUBTYPE//NONSGML Subtype Appointment//EN">appt;
print "-//XAPIA/CSA/ENTRYATTR//NONSGML
Classification//EN:uinteger:0">appt;
printf("-//XAPIA/CSA/ENTRYATTR//NONSGML End
Date//EN:datetime:%s\n",fdate)>appt;
print "-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Show
Time//EN:sinteger:0">appt;
printf("-//XAPIA/CSA/ENTRYATTR//NONSGML Summary//EN:string: %s
%.4d\n",easter[lang],y)>appt;
print "-//XAPIA/CSA/ENTRYATTR//NONSGML Status//EN:uinteger:2304">appt;
printf("-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Repeat
Type//EN:sinteger:0\n")>appt;
printf("-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Repeat
Times//EN:uinteger:0\n")>appt;
print "-//XAPIA/CSA/ENTRYATTR//NONSGML Audio
Reminder//EN:reminder:300:">appt;
print "-//XAPIA/CSA/ENTRYATTR//NONSGML Popup
Reminder//EN:reminder:300:">appt;
print "-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Repeat Occurrence
Number//EN:sinteger:-1">appt;
print "-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Repeat
Interval//EN:uinteger:0">appt;
print "-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Entry
Delimiter//EN:string:end">appt;
printf("\tDate: %s/%s/%s\n",m,d,y)>appt;
printf("\tStart: 0241\n",shour,smin)>appt
printf("\tEnd: 0242\n",fhour,fmin)>appt
printf("\tRepeat: One Time\n")>appt;
printf("\tFor: 0\n")>appt;
printf("\tWhat: %s %.4d\n",easter[lang],y)>appt;
printf("\t")>appt;
# Ascension day is 40 days after easter
aday=r+39;
# print aday; # for debugging purpose only !
m=3;
if (aday>31) {aday-=31;m++ }
if (aday>30) {aday-=30;m++ }
if (aday>31) {aday-=31;m++}
if (aday>30) {aday-=30;m++}
sdate=sprintf("%.4d%.2d%.2dT004100Z",aday,m,y);
fdate=sprintf("%.4d%.2d%.2dT004200Z",aday,m,y);
appt="ascension_"y;
printf("\n\n") >appt
print "\t** Calendar Appointment **" >appt
print "-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Entry
Delimiter//EN:string:begin">appt;
printf("-//XAPIA/CSA/ENTRYATTR//NONSGML Start
Date//EN:datetime:%s\n",sdate)>appt;
print "-//XAPIA/CSA/ENTRYATTR//NONSGML Type//EN:uinteger:0">appt;
print "-//XAPIA/CSA/ENTRYATTR//NONSGML
Subtype//EN:string:-//XAPIA/CSA/SUBTYPE//NONSGML Subtype Appointment//EN">appt;
print "-//XAPIA/CSA/ENTRYATTR//NONSGML
Classification//EN:uinteger:0">appt;
printf("-//XAPIA/CSA/ENTRYATTR//NONSGML End
Date//EN:datetime:%s\n",fdate)>appt;
print "-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Show
Time//EN:sinteger:0">appt;
printf("-//XAPIA/CSA/ENTRYATTR//NONSGML Summary//EN:string: %s
%.4d\n",ascension[lang],y)>appt;
print "-//XAPIA/CSA/ENTRYATTR//NONSGML Status//EN:uinteger:2304">appt;
printf("-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Repeat
Type//EN:sinteger:0\n")>appt;
printf("-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Repeat
Times//EN:uinteger:0\n")>appt;
print "-//XAPIA/CSA/ENTRYATTR//NONSGML Audio
Reminder//EN:reminder:300:">appt;
print "-//XAPIA/CSA/ENTRYATTR//NONSGML Popup
Reminder//EN:reminder:300:">appt;
print "-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Repeat Occurrence
Number//EN:sinteger:-1">appt;
print "-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Repeat
Interval//EN:uinteger:0">appt;
print "-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Entry
Delimiter//EN:string:end">appt;
printf("\tDate: %s/%s/%s\n",m,aday,y)>appt;
printf("\tStart: 0241\n",shour,smin)>appt
printf("\tEnd: 0242\n",fhour,fmin)>appt
printf("\tRepeat: One Time\n")>appt;
printf("\tFor: 0\n")>appt;
printf("\tWhat: %s %.4d\n",ascension[lang],y)>appt;
printf("\t")>appt;
# Whit Monday is 50 days after easter
wday=r+48;
m=3;
if (wday>31) {wday-=30;m++}
if (wday>30) {wday-=30;m++}
if (wday>31) {wday-=31;m++}
if (wday>30) {wday-=30;m++}
sdate=sprintf("%.4d%.2d%.2dT004100Z",wday,m,y);
fdate=sprintf("%.4d%.2d%.2dT004200Z",wday,m,y);
appt="whit_"y;
printf("\n\n") >appt
print "\t** Calendar Appointment **" >appt
print "-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Entry
Delimiter//EN:string:begin">appt;
printf("-//XAPIA/CSA/ENTRYATTR//NONSGML Start
Date//EN:datetime:%s\n",sdate)>appt;
print "-//XAPIA/CSA/ENTRYATTR//NONSGML Type//EN:uinteger:0">appt;
print "-//XAPIA/CSA/ENTRYATTR//NONSGML
Subtype//EN:string:-//XAPIA/CSA/SUBTYPE//NONSGML Subtype Appointment//EN">appt;
print "-//XAPIA/CSA/ENTRYATTR//NONSGML
Classification//EN:uinteger:0">appt;
printf("-//XAPIA/CSA/ENTRYATTR//NONSGML End
Date//EN:datetime:%s\n",fdate)>appt;
print "-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Show
Time//EN:sinteger:0">appt;
printf("-//XAPIA/CSA/ENTRYATTR//NONSGML Summary//EN:string: %s
%.4d\n",whit[lang],y)>appt;
print "-//XAPIA/CSA/ENTRYATTR//NONSGML Status//EN:uinteger:2304">appt;
printf("-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Repeat
Type//EN:sinteger:0\n")>appt;
printf("-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Repeat
Times//EN:uinteger:0\n")>appt;
print "-//XAPIA/CSA/ENTRYATTR//NONSGML Audio
Reminder//EN:reminder:300:">appt;
print "-//XAPIA/CSA/ENTRYATTR//NONSGML Popup
Reminder//EN:reminder:300:">appt;
print "-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Repeat Occurrence
Number//EN:sinteger:-1">appt;
print "-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Repeat
Interval//EN:uinteger:0">appt;
print "-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Entry
Delimiter//EN:string:end">appt;
printf("\tDate: %s/%s/%s\n",m,wday,y)>appt;
printf("\tStart: 0241\n",shour,smin)>appt
printf("\tEnd: 0242\n",fhour,fmin)>appt
printf("\tRepeat: One Time\n")>appt;
printf("\tFor: 0\n")>appt;
printf("\tWhat: %s %.4d\n",whit[lang],y)>appt;
printf("\t")>appt;
}
# We can also calculate the date of Pentecost (Whit Sunday/Monday) = Easter +50
days
# and of Ascension Day = Easter + 4O days
# To write to files in awk, it is enough to do print(f) something > FILE
------------------------------------------------------------------------------
What NetFlow Analyzer can do for you? Monitors network bandwidth and traffic
patterns at an interface-level. Reveals which users, apps, and protocols are
consuming the most bandwidth. Provides multi-vendor support for NetFlow,
J-Flow, sFlow and other flows. Make informed decisions using capacity planning
reports. http://sdm.link/zohomanageengine
_______________________________________________
cdesktopenv-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/cdesktopenv-devel