Calendar View
The following code produces the calendar view from a csv file. Suppose you have a CSV file like this
name,start,end
france,2019-02-10,2019-04-02
england,2019-05-01,2019-09-12
you can run the following command
python calview.py csvfile
to have the calendar view in an HTML page. See the original calendar view here
import pandas as pd
import datetime
import sys
from string import Template
'''
Produces the calendar view from a csv file.
USAGE
python calview.py csvfile
The input (csvfile) looks like this
name,start,end
france,2019-02-10,2019-04-02
england,2019-05-01,2019-09-12
The output is a calendar view in an HTML page.
'''
# input
csvfile=sys.argv[1]
#
data=pd.read_csv(csvfile,parse_dates=[1,2])
begin_yr=data['start'].min().year
end_yr=data['end'].max().year
ind=pd.date_range(datetime.date(begin_yr,1,1),datetime.date(end_yr,12,31))
vacation_dates=[]
for vac in data.index:
vacation_dates.append([1 if date in pd.date_range(data['start'][vac],data['end'][vac]) else 0 for date in ind])
names=[name for name in data.name]
df=pd.concat([pd.Series(list) for list in vacation_dates],axis=1)
df.columns=names
df['date']=ind
#value=df['france'] | df['england']
event=df[df.columns.drop('date')].any(axis=1) # returns true if there is an event on that day
value=event.apply(lambda x: 1 if x else 0)
df['value']=value
datastring=repr(df.to_csv(index=False))
# output
t=Template('<!DOCTYPE html>\r\n<meta charset="utf-8">\r\n\r\n<style>\r\n\r\n/* set the CSS */\r\n\r\n</style>\r\n\r\n<body>\r\n\r\n<div id="xy"style="border:solid black 1px;"></div>\r\n\r\n<!-- load the d3.js library -->\r\n<script src="https://d3js.org/d3.v5.min.js"></script>\r\n<script>\r\n\r\n\r\ndatastring=$datastring\r\nvar data=d3.csvParse(datastring,d3.autoType)\r\n//;\r\n\r\n//vardata=dataset => d.date.getUTCFullYear();//d3.json(dataset,d3.autoType);\r\n\r\nvar weekday="monday";\r\nvar cellSize= 20;\r\nvar width = 1000;\r\nvar height = cellSize * (weekday === "weekday" ?7 : 9);\r\n\r\nvar timeWeek = d3.utcMonday;\r\nvar countDay = d =>(d.getUTCDay() + 6) % 7 ;// looks like its for sunday week, can be takenout\r\nfunction pathMonth(t) {\r\n const n = weekday === "weekday" ? 5 : 7;\r\n const d = Math.max(0, Math.min(n, countDay(t)));\r\n const w =timeWeek.count(d3.utcYear(t), t);\r\n return `$${d === 0 ? `M$${w *cellSize},0`\r\n : d === n ? `M$${(w + 1) * cellSize},0`\r\n : `M$${(w +1) * cellSize},0V$${d * cellSize}H$${w * cellSize}`}V$${n *cellSize}`;\r\n}\r\nvar format = d3.format("+.2%");\r\nvar formatDate =d3.utcFormat("%x");\r\nvar formatDay = d => "SMTWTFS"[d.getUTCDay()]; //"SMTWTFS"[1] = S;\r\nvar formatMonth = d3.utcFormat("%b");\r\nvar color =d3.scaleSequential(d3.interpolatePiYG).domain([0, 1]);\r\n\r\nconst years =d3.nest()\r\n .key(d => d.date.getUTCFullYear())\r\n .entries(data)\r\n.reverse();\r\n\r\nconst svg=d3.select("#xy")\r\n .append("svg")\r\n.attr("width",width)\r\n .attr("height","height*years.length")\r\n.style("font", "10px sans- serif")\r\n .style("width", "100%")\r\n.style("height", "auto");\r\n\r\nconst year= svg.selectAll("g")\r\n.data(years)\r\n .join("g")\r\n .attr("transform", (d, i) =>`translate(40,$${height * i + cellSize *1.5})`);\r\n\r\nyear.append("text")\r\n .attr("x", -5)\r\n .attr("y",-5)\r\n .attr("font-weight", "bold")\r\n .attr ("text-anchor", "end")\r\n.text(d => d.key);\r\n\r\nyear.append("g")\r\n .attr("text-anchor","end")\r\n.selectAll("text")\r\n.data((weekday === "weekday" ? d3.range(2, 7): d3.range(7)).map(i => new Date(1995, 0, i)))\r\n.join("text")\r\n .attr("x",-5)\r\n .attr("y", d => (countDay(d) + 0.5) * cellSize)\r\n .attr("dy","0.31em")\r\n .text(formatDay);\r\n\r\nyear.append("g")\r\n.selectAll("rect")\r\n.data(d =>d.values)\r\n.join("rect")\r\n .attr("width", cellSize - 1)\r\n.attr("height", cellSize - 1)\r\n .attr("x", d =>timeWeek.count(d3.utcYear(d.date), d.date) * cellSize + 0.5)\r\n .attr("y", d=> countDay(d.date) * cellSize + 0.5)\r\n .attr("fill", d =>color(d.value))\r\n.append("title")\r\n .text(d => `$${formatDate(d.date)}:$${format(d.value)}`);\r\n\r\nconst month =year.append("g")\r\n.selectAll("g")\r\n.data(d =>d3.utcMonths(d3.utcMonth(d.values[0].date), d.values[d.values.length -1].date))\r\n.join("g");\r\n\r\nmonth.filter((d, i) => i).append("path")\r\n.attr("fill", "none")\r\n .attr("stroke", "#fff")\r\n .attr("stroke-width",3)\r\n .attr("d", pathMonth);\r\n\r\nmonth.append("text")\r\n .attr("x", d =>timeWeek.count(d3.utcYear(d), timeWeek.ceil(d)) * cellSize + 2)\r\n .attr("y",-5)\r\n .text(formatMonth);\r\n\r\n\r\n</script>\r\n\r\n</body>\r\n')
html_text=t.safe_substitute(datastring=datastring)
with open('htmlfile.html','w') as html:
html.write(html_text)
print(repr(datastring))