#!/usr/bin/env python
# -*- encoding: utf-8 -*-
# vim:syntax=python
# http://holidata.net/en-US/2016.json
"""
This script downloads data from holidata.net and writes it into files in the current directory.
Its output formats are parseable by timewarrior (https://taskwarrior.org/docs/timewarrior/).
This is very alpha. Since holidata.net has a few minor mistakes for Germany I'm writing this to
test.xx-YY for now (I've just reported these, so allow the guys some time :) ). The files
are still sourcable with that name :)
Also, for now this script only downloads de-DE. You will notice the complete lack of a main()
definition, that is the next step: it will also carry parameters so you can download your
own stuff.
Finally, I'm fixing the ISO-3166-2 violation for North Rhine Westphalia - holidata.net has de-NRW.
That is the next bug to fix for them :)
tl;dr
SCRIPT IS NOT FINISHED, THIS IS A GIT - USE ONLY IF YOU UNDERSTAND AND IF YOU ARE FROM ZE GERMANY
"""
#import os, sys, re, time, argparse
import json, sys
reload(sys)
sys.setdefaultencoding('utf8')
from datetime import datetime
from time import sleep
if sys.version_info >= (3, 0):
from urllib.request import urlopen
from urllib.error import HTTPError
else:
from urllib2 import urlopen, HTTPError
__hheader__ = "# File auto-generated by lirion.de's refresh,\n" \
"# Date: " + datetime.strftime(datetime.now(), "%Y-%m-%d %H:%M:%S %z") + "\n" \
"# data provided by holidata.net\n\n" \
"define holidays:\n"
def headwrite(file):
"""
This writes the default header to the file it is being passed on. Content see
__hheader__ right above.
"""
try:
open(file, 'w').close()
except IOError:
print("Cannot write to %s!", file)
exit(2)
with open(file, "a") as ofile:
#f = open(ofile, "a")
ofile.write(__hheader__)
def hfetch(locode, year):
"""
This function downloads the holiday data for a given ISO-3166 code from holidata.net
It will return a single string containing all of the JSON.
"""
myurl = "https://holidata.net/" + mylocode + "/" + myyear + ".json"
try:
lines = urlopen(myurl).read().decode('utf-8')
except HTTPError as httpe:
if httpe.code == 404:
print("holidata.net does not have data for %s(%s), for %d." % (mylocale, myregion,
mydate))
else:
print(httpe.code, httpe.read())
return lines
def hparse(lines, locode, year):
"""
This function parses the JSON string we expect from holidata.net and writes its fragments to
the specific region files, if a region is given. So, e.g.: a holiday for all of the US will
not have a region definition and thus be written to file.en-US, whereas a holiday that is not
valid for all of the US but is valid for Oregon will be written to file.en-OR.
"""
islocdef = { 'XY-ZZ': 1 }
for line in lines.split('\n'):
if line:
#sys.stdout.write(".")
jdata = json.loads(line)
mylocale = unicode(jdata['locale'])
mycountry = mylocale.split('-')[0]
myregion = unicode(jdata['region'])
if myregion == "":
myregion = mylocale.split('-')[1]
# holidata.net violates ISO-3166-2:DE here:
if myregion == "NRW":
myregion = "NW" # or Neustadt/Weinstr., Palz > Pott
myhlocale = unicode(mycountry + "-" + myregion)
if jdata['date'] == "":
print("%s has no date given for %s!", jdata['description'], jdata['locale'])
mydate = unicode('1970_01_01')
else:
mydate = unicode(datetime.strftime(datetime.strptime(jdata['date'], '%Y-%m-%d'),
'%Y_%m_%d'))
myfile = "test." + myhlocale
if myhlocale not in islocdef:
headwrite(myfile)
with open(myfile, "a") as ofile:
#f = open(ofile, "a")
ofile.write(" " + mycountry + "-" + myregion + ":\n")
islocdef[myhlocale] = myhlocale
with open(myfile, "a") as ofile:
ofile.write(" " + mydate + " = " + unicode(jdata['description']) + "\n")
#print("%s (%s), %s, %s: %s" % (unicode(jdata['description']), unicode(jdata['region']),
# mycountry, myregion, mydate))
sleep(0.1)
sys.stdout.flush()
print islocdef.keys()
if __name__ == "__main__":
myyear = ""
mylocode = ""
if myyear == "":
now = datetime.now()
myyear = unicode(now.year)
if mylocode == "":
mylocode = "de-DE"
sys.stdout.write("Fetching holiday data from holidata.net...")
sys.stdout.flush()
lines = hfetch(mylocode, myyear)
print(" done.")
if lines == "":
print("No lines returned from holidata.net for %s!", mylocode)
exit(3)
sys.stdout.write("Parsing data")
sys.stdout.flush()
hparse(lines, mylocode, myyear)
print(" done.")
ant;}
div#cgit div.footer a {color:#666!important;}
#cgit h1,#cgit h2,#cgit h3 {
font-family:"Telex","Helvetica Neue",Helvetica,Arial,sans-serif;
}
div#cgit table#header td.main {word-spacing:0.1em;}
/*div#cgit pre {white-space:pre-wrap;} :( */
footer {margin-bottom:2em;}
section:nth-last-child(3) {margin-bottom:5em;}
section h2 {text-align:center;margin-top:0;padding-top:0;}
section a {text-decoration:none;}
section a, section a:visited {color:#007a37;}
section a:hover, section a:active {color:#e56b00;}
#links ul {list-style-type:none;text-transform:lowercase;}
/*#links ul li {border-bottom:1px solid #e0e0e0;padding:0.4em 0 0.3em 0;width:15em;margin:0 auto;text-align:center;}*/
#links ul li {padding:0.2em 0 0.3em 2em;margin:0.1em 0 0.1em 0;width:19em;}
#links ul li:nth-child(2n) {float:right;}
#links ul li:nth-child(4n) {background:rgba(80,80,80,0.1);}
#links ul li:nth-child(2n+1) {float:left;}
#links ul li:nth-child(4n-1) {background:rgba(80,80,80,0.1);}
#links:after {clear:both;content:" ";display:block;}
#teamspeak_srv {background-color:rgba(225,245,220,0.7);}
#teamspeak_srv>div.content {margin:0 auto;font-size:13px;width:29.5em;font-family:"Telex","Helvetica Neue",Helvetica,Arial,sans-serif;}
#teamspeak_srv div.copy { display:none!important; }
#teamspeak_srv .content:last-child { margin-bottom:2em; }
aside#ts3remark {margin-top:4em;font-size:66%;text-align:center;font-style:italic;}
#validate {
transform: rotate(45deg);
/*-webkit-transform: rotate(45deg); /*FUCK YOU CHROME, SAFARI AND OPERA*/
/*-ms-transform: rotate(45deg); /*FUCK YOU INTERNET EXPLORER 9 AND BELOW*/
position:fixed;bottom:0;left:0;text-align:center;text-transform:lowercase;width:100%;margin-left:-45.666%;margin-bottom:1.666em;
}
#validate > p {margin:0;font-weight:bold;}
#validate a {text-decoration:none;}
#validate a:hover{text-decoration:none;}
#validate > p:first-child {/*background:#0092bf;*/color:white;border-top:1px solid;border-color:#058;background:rgba(0,126,178,.8);}
#validate > p:nth-child(2) {/*background:#90c140;*/color:white;border-bottom:1px solid;border-color:#591;background:rgba(124,178,54,.8);}
#validate > p a {
color:white;display:inline-block;padding:0.3em 25px 0.3em 0.3em;box-sizing:content-box;height:100%;
background-size:auto 24px;
}
#validate > p:first-child a {
background:transparent url('/flags/html5.png') right center no-repeat scroll;
}
#validate > p:nth-child(2) a {
background:transparent url('/flags/css3.png') right center no-repeat scroll;
}
#validate > p span:last-child {display:none;}
/*#validate > p:last-child a {color:#3e7000;}
#validate > p:last-child a:hover {color:#c9910e;}*/
/*#mail h2:before {content:"\2709\fe0f\000a";display:block;font-size:4em;}*/
#mail h2:before {content:"\2709";display:block;font-size:4em;}
#mail,#philosophy,#hots {text-align:justify;}
#mail h2:before, #philosophy h2:before,#hots h2:before {
font-family:"Elusive Icons";
display:block;font-size:3em;font-weight:normal;
}
#mail h2:before {content:"\e6e1";}
#mail .remark,#philosophy .remark,#hots .remark {font-size:80%;margin-top:2em;font-style:italic;}
#mail strong,#philosophy strong {color:#a00;}
/*#philosophy h2:before {content:"\262f\fe0f\000a";display:block;font-size:4em;}*/
#philosophy h2:before {content:"\262f";}
#hots h2:before {
content:" ";
background:transparent url('//lirion.de/heroes-of-the-storm.svg') center center;
background-size:1.5em 1.5em;
width:1.5em;height:1.5em;text-align:center;margin:0 auto;padding:0;display:block;
}
#hots p#hotslogs {text-align:center; margin:0 auto;margin-bottom:1em;}
#rebuild {text-decoration:blink;color:#30c000;}
#os-releases {/*width:66.6%;*/margin-left:2em;}
#os-releases th {text-align:left;}
#os-releases tr:nth-child(2n-1) td {background-color:#bcd1c1;}
#os-releases tr td,#os-releases tr th {padding:0 0.75em;}
#os-releases tr td.hash {font-family:"DejaVu Sans Mono",Monospace,monospace,serif;font-size:90%;}
#nowww {
position:fixed;top:4em;right:1em;margin:0;padding:0;
background:transparent url('/assets/no_www.png') bottom right no-repeat;
background-size:80px auto;width:80px;height:80px;
}
#nowww a {
display:block;margin:0;padding:0;
width:80px;height:80px;
}
#nowww a span {display:none;}
div.markdown-body p:last-child { padding-bottom:1.5em; }
div#cgit {margin-bottom:2em;}
@keyframes fadeDown {
0% {
opacity: 0;
transform: translateY(-20px);
}
100% {
opacity: 1;
transform: translateY(0);
}
}
.fadeDown, header {
animation:fadeDown 1s ease;
}
/* jekyll */
header.post-header { margin-top: 0.1337em; }
.post h1 { font-size:2.1337em; text-align: left; }
.post h1+p { text-align: left; }
ul.post-list {
background: #f0f0f0;
list-style: none;
padding-inline-start: 0;
padding: 0.8em;
}
ul.post-list li { padding:0.4em; }
ul.post-list li:nth-child(2n-1) { background-color:#ffffff; }
ul.post-list li span.post-meta {
font-weight: bold;font-style: oblique;font-size:100%;
}
ul.post-list li span.post-meta:after { content: ':'; }
ul.post-list li h3 {
font-size: 100%;font-weight: normal; display: inline;
margin-left: 1em;
font-family: "Telex","Helvetica Neue",Helvetica,Arial,sans-serif;
border-bottom: none;
}
ul.post-list li h3 a {
text-decoration: none;
}
nav.blog-nav {
background: transparent;
position: static;
border: none;
}
.blog-nav .nav-trigger { display:none; }
.blog-nav .menu-icon { display:none; }
.post-content table {
margin-bottom: 30px;
width: 100%;
text-align: left;
color: #3f3f3f;
border-collapse: collapse;
border: 1px solid #d0d0d0; }
.post-content table tr:nth-child(odd) {
background-color: #e0e0e0; }
.post-content table tr:nth-child(even) {
background-color: #f0f0f0; }
.post-content table th, table td {
padding: 10px 15px; }
.post-content table th {
background-color: #f0f0f0;
border: 1px solid #dedede;
border-bottom-color: #c9c9c9; }
.post-content table td {
border: 1px solid #e8e8e8; }
.blog-nav a.page-link {
text-decoration: none;
font-size:110%;
border-left: 1px solid;
border-right: 1px solid;
margin-left: 0.1em;margin-right:0.1em;
padding-left:0.7331em;padding-right: 0.7331em;
display: inline-block;
}
.blog-nav a.page-link:first-child {
margin-left: 0;
border-left: 0;
}
.blog-nav a.page-link:last-child {
margin-right: 0;
border-right: 0;
}
figure.highlight {
margin: 0 auto;
margin-left: 1em;
padding: 0.666em;
}
figure.highlight pre {
margin-top: 0;
margin-bottom: 0;
overflow-x: auto;
overflow-y: hidden;
}
figure.highlight pre code, code.highlighter-rouge {
font-size: 0.8em;
}
article.post div.post-content, #tocw {
background: rgba(251,255,253,0.6);
padding: 0.666em;
}
main.page-content a, footer.site-footer a {
text-decoration: none;
color: #169b62;
font-weight: 550;
}
main.page-content a:hover, footer.site-footer a:hover, main.page-content a:active,
footer.site-footer a:active {
color: #ff883e;
}
.highlight { background: #e8fff0; }
#tocw ol {
list-style-type: decimal;
counter-reset: item;
padding-left: 10px;
}
#tocw ol li {
display: block;
}
#tocw > ol > li {
padding-left: 0.5em;
}
#tocw > ol > li > ol > li {
padding-left: 0.666em;
}
#tocw > ol > li > ol > li > ol > li {
padding-left: 1.337em;
}
#tocw ol li:before {
content: counters(item, ".") ". ";
counter-increment: item
}
/*main.page-content h2:before {
content: counter(heading)". ";
counter-increment: heading;
}
main.page-content h2 {
counter-reset: subheading;
}
main.page-content h3:before {
content: counter(heading)"." counter(subheading)". ";
counter-increment: subheading;
}*/
/**
* Syntax highlighting styles
*/
.highlight {
background: #fff; }
.highlighter-rouge .highlight {
background: #eef; }
.highlight .c {
color: #998;
font-style: italic; }
.highlight .err {
color: #a61717;
background-color: #e3d2d2; }
.highlight .k {
font-weight: bold; }
.highlight .o {
font-weight: bold; }
.highlight .cm {
color: #998;
font-style: italic; }
.highlight .cp {
color: #999;
font-weight: bold; }
.highlight .c1 {
color: #998;
font-style: italic; }
.highlight .cs {
color: #999;
font-weight: bold;
font-style: italic; }
.highlight .gd {
color: #000;
background-color: #fdd; }
.highlight .gd .x {
color: #000;
background-color: #faa; }
.highlight .ge {
font-style: italic; }
.highlight .gr {
color: #a00; }
.highlight .gh {
color: #999; }
.highlight .gi {
color: #000;
background-color: #dfd; }
.highlight .gi .x {
color: #000;
background-color: #afa; }
.highlight .go {
color: #888; }
.highlight .gp {
color: #555; }
.highlight .gs {
font-weight: bold; }
.highlight .gu {
color: #aaa; }
.highlight .gt {
color: #a00; }
.highlight .kc {
font-weight: bold; }
.highlight .kd {
font-weight: bold; }
.highlight .kp {
font-weight: bold; }
.highlight .kr {
font-weight: bold; }
.highlight .kt {
color: #458;
font-weight: bold; }
.highlight .m {
color: #099; }
.highlight .s {
color: #d14; }
.highlight .na {
color: #008080; }
.highlight .nb {
color: #0086B3; }
.highlight .nc {
color: #458;
font-weight: bold; }
.highlight .no {
color: #008080; }
.highlight .ni {
color: #800080; }
.highlight .ne {
color: #900;
font-weight: bold; }
.highlight .nf {
color: #900;
font-weight: bold; }
.highlight .nn {
color: #555; }
.highlight .nt {
color: #000080; }
.highlight .nv {
color: #008080; }
.highlight .ow {
font-weight: bold; }
.highlight .w {
color: #bbb; }
.highlight .mf {
color: #099; }
.highlight .mh {
color: #099; }
.highlight .mi {
color: #099; }
.highlight .mo {
color: #099; }
.highlight .sb {
color: #d14; }
.highlight .sc {
color: #d14; }
.highlight .sd {
color: #d14; }
.highlight .s2 {
color: #d14; }
.highlight .se {
color: #d14; }
.highlight .sh {
color: #d14; }
.highlight .si {
color: #d14; }
.highlight .sx {
color: #d14; }
.highlight .sr {
color: #009926; }
.highlight .s1 {
color: #d14; }
.highlight .ss {
color: #990073; }
.highlight .bp {
color: #999; }
.highlight .vc {
color: #008080; }
.highlight .vg {
color: #008080; }
.highlight .vi {
color: #008080; }
.highlight .il {
color: #099; }
git.lirion.de
Of git, get, and gud