summaryrefslogtreecommitdiff
path: root/ebus/webapp
diff options
context:
space:
mode:
Diffstat (limited to 'ebus/webapp')
-rw-r--r--ebus/webapp/static/console.html77
-rw-r--r--ebus/webapp/static/draw.svg112
-rw-r--r--ebus/webapp/static/lib/d3-v2.6.1/d3.time.js687
3 files changed, 789 insertions, 87 deletions
diff --git a/ebus/webapp/static/console.html b/ebus/webapp/static/console.html
index 054d5d4..b8b732b 100644
--- a/ebus/webapp/static/console.html
+++ b/ebus/webapp/static/console.html
@@ -1,20 +1,23 @@
<html>
<head>
<script src="lib/d3-v2.6.1/d3.js"></script>
+ <script src="lib/d3-v2.6.1/d3.time.js"></script>
<style>
path {
stroke: steelblue;
stroke-width: 2;
fill: none;
}
-
line {
stroke: black;
}
div.popup {
position: absolute;
border: 2px solid gray;
- background-color: yellow;
+ background-color: #fefefe;
+ }
+ div.popup .plot {
+ margin: 5px;
}
#log {
height: 300px;
@@ -34,8 +37,11 @@
"boilerWert" : "feuerungsautomat1.betriebsdatenRegler1.boilerTemperatur"
};
function timeToString(timestamp) {
- var f = d3.format("02d");
var d = new Date();
+ return dateToString(d);
+ }
+ function dateToString(d) {
+ var f = d3.format("02d");
return f(d.getHours()) + ":" + f(d.getMinutes()) + ":" + f(d.getSeconds());
}
function log(data) {
@@ -82,28 +88,77 @@
var w = 550, h = 200, margin = 20;
var plot = popup.append("svg:svg")
+ .classed("plot", true)
.attr("width", w)
.attr("height", h);
- var startdate = (new Date().getTime()/1000) - 1*60*60*24
+ var wait_indicator = plot.append("svg:text")
+ .attr("x", w/2)
+ .attr("y", h/2)
+ .text("Bitte Warten");
+
+ var startdate = (new Date().getTime()/1000) - 7*60*60*24
var enddate = (new Date().getTime()/1000)
d3.json("../sensor/"+sensor_name+"/" + startdate + "/" + enddate, function(resp) {
+ var data = resp.data.map(function(d) {
+ return [new Date(d[0]), d[1]];
+ })
+ var x_min = d3.min(data, function(d){return d[0]}),
+ x_max = d3.max(data, function(d){return d[0]}),
+ y_min = d3.min(data, function(d){return d[1]}),
+ y_max = d3.max(data, function(d){return d[1]});
+
var y = d3.scale.linear()
- .domain([0, d3.max(resp.data, function(d){return d[1];})])
+ .domain([y_min, y_max])
.range([0+margin, h-margin]);
- var x = d3.scale.linear()
- .domain([0, resp.data.length])
- .range([0+margin, w-margin]);
+ var x = d3.time.scale()
+ .domain([x_min, x_max])
+ .range([0+margin, w-margin]);
+
var g = plot.append("svg:g")
.attr("transform", "translate(0, "+h+")");
var line = d3.svg.line()
- .x(function(d,i){return x(i); })
- .y(function(d) {return -1 * y(d[1]);});
+ .x(function(d,i){ return x(d[0]); })
+ .y(function(d) {return -1*y(d[1]);});
g.append("svg:path")
- .attr("d", line(resp.data));
+ .attr("d", line(data));
+
+ // Axes
+ g.append("svg:line")
+ .attr("x1", x(x_min))
+ .attr("y1", -1 * y(y_min))
+ .attr("x2", x(x_max))
+ .attr("y2", -1 * y(y_min));
+
+ g.append("svg:line")
+ .attr("x1", x(x_min))
+ .attr("y1", -1*y(y_min))
+ .attr("x2", x(x_min))
+ .attr("y2", -1*y(y_max));
+
+
+ // Ticks
+ var tick_format = d3.time.format("%d.%m");
+ g.selectAll(".xlabel")
+ .data(x.ticks(5)).enter()
+ .append("svg:text")
+ .text(function(d){return tick_format(d) })
+ .attr("x", function(d) { return x(d) })
+ .attr("y", 0)
+ .attr("text-anchor", "middle");
+
+ g.selectAll(".ylabel")
+ .data(y.ticks(5)).enter()
+ .append("svg:text")
+ .text(String)
+ .attr("x", 0)
+ .attr("y", function(d) {return -1*y(d)})
+ .attr("text-anchor", "right");
+
+ wait_indicator.remove();
});
});
}
diff --git a/ebus/webapp/static/draw.svg b/ebus/webapp/static/draw.svg
index b1a5480..6a9055c 100644
--- a/ebus/webapp/static/draw.svg
+++ b/ebus/webapp/static/draw.svg
@@ -38,30 +38,6 @@
id="linearGradient9274"
xlink:href="#linearGradient14630"
inkscape:collect="always" />
- <filter
- id="filter8363"
- height="1.682261"
- y="-0.3411305"
- width="1.2516437"
- x="-0.12582178"
- inkscape:collect="always">
- <feGaussianBlur
- id="feGaussianBlur8365"
- stdDeviation="5.4634181"
- inkscape:collect="always" />
- </filter>
- <filter
- id="filter6454"
- height="1.3779083"
- y="-0.1889542"
- width="1.1359831"
- x="-0.06799154"
- inkscape:collect="always">
- <feGaussianBlur
- id="feGaussianBlur6456"
- stdDeviation="7.2835937"
- inkscape:collect="always" />
- </filter>
<linearGradient
y2="1102.4946"
x2="94.621376"
@@ -342,14 +318,6 @@
id="linearGradient4463"
xlink:href="#linearGradient14625"
inkscape:collect="always" />
- <filter
- id="filter4458"
- inkscape:collect="always">
- <feGaussianBlur
- id="feGaussianBlur4460"
- stdDeviation="8.8447956"
- inkscape:collect="always" />
- </filter>
<linearGradient
gradientTransform="translate(-385.82338,59.419123)"
gradientUnits="userSpaceOnUse"
@@ -448,9 +416,9 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="0.98994949"
- inkscape:cx="271.95772"
- inkscape:cy="105.68883"
+ inkscape:zoom="1.4"
+ inkscape:cx="150.59342"
+ inkscape:cy="208.20173"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
@@ -501,52 +469,17 @@
id="tspan2989"
x="14.663156"
y="903.1358">Heizkessel</tspan></text>
- <rect
- style="opacity:0.98000004;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.58299994;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:3.166, 1.583;stroke-dashoffset:0"
- id="rect2991"
- width="11.1117"
- height="76.771591"
- x="202.60992"
- y="745.44818" />
- <rect
- style="opacity:0.98000004;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.58299994;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:3.166, 1.583;stroke-dashoffset:0"
- id="rect2991-1"
- width="11.1117"
- height="76.771591"
- x="283.16959"
- y="745.44818" />
- <rect
- style="opacity:0.98000004;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.58299994;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:3.166, 1.583;stroke-dashoffset:0"
- id="rect2991-9"
- width="11.1117"
- height="76.771591"
- x="242.88974"
- y="745.44818" />
- <rect
- style="opacity:0.98000004;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.58299994;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:3.166, 1.583;stroke-dashoffset:0"
- id="rect2991-4"
- width="11.1117"
- height="76.771591"
- x="222.74985"
- y="745.44818" />
- <rect
- style="opacity:0.98000004;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.58299994;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:3.166, 1.583;stroke-dashoffset:0"
- id="rect2991-7"
- width="11.1117"
- height="76.771591"
- x="263.02966"
- y="745.44818" />
<text
xml:space="preserve"
style="font-size:18.44056702px;font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Linux Biolinum Slanted O;-inkscape-font-specification:Linux Biolinum Slanted O Bold Italic"
- x="200.30336"
- y="733.60901"
+ x="206.36427"
+ y="743.71051"
id="text2987-8"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan2989-4"
- x="200.30336"
- y="733.60901">Kollektor: <tspan
+ x="206.36427"
+ y="743.71051">Kollektor: <tspan
style="font-weight:normal;-inkscape-font-specification:Linux Biolinum Slanted O Italic"
id="tempkollektorWert">XXX</tspan> °C</tspan></text>
<path
@@ -603,7 +536,7 @@
sodipodi:cy="362.11163"
sodipodi:rx="29.7995"
sodipodi:ry="48.487324"
- d="m 97.984795,362.11163 a 29.7995,48.487324 0 1 1 -59.598999,0 29.7995,48.487324 0 1 1 59.598999,0 z"
+ d="m 97.984795,362.11163 c 0,26.77881 -13.341691,48.48733 -29.7995,48.48733 -16.457809,0 -29.799499,-21.70852 -29.799499,-48.48733 0,-26.77881 13.34169,-48.48732 29.799499,-48.48732 16.457809,0 29.7995,21.70851 29.7995,48.48732 z"
transform="matrix(1.0481376,0,0,0.60942325,296.73303,720.89972)" />
<text
xml:space="preserve"
@@ -622,7 +555,7 @@
style="opacity:0.98000004;fill:#ffff00;fill-opacity:1;stroke:#ffff00;stroke-width:0.82573485;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1.65146976, 0.82573488;stroke-dashoffset:0"
inkscape:transform-center-x="0.98497389"
inkscape:transform-center-y="-1.2124102"
- d="m 326.96911,775.75069 -12.1917,-15.84216 9.87347,17.80337 -9.97137,-17.3258 7.41242,18.96052 -7.5731,-18.50027 4.81909,19.77933 -5.03968,-19.34459 2.13976,20.24516 -2.41633,-19.84371 -0.57774,20.34973 0.25013,-19.98872 -3.28494,20.09116 2.91214,-19.77704 -5.93352,19.47405 5.52217,-19.21242 -8.47622,18.50944 8.03367,-18.30497 -10.86765,17.21451 10.40181,-17.07085 -13.06517,15.6124 12.58432,-15.53212 -15.02951,13.73169 14.54226,-13.71621 -16.72567,11.60593 16.2407,-11.65553 -18.12335,9.27305 17.64932,-9.38685 -19.19762,6.77471 18.74299,-6.95068 -19.92931,4.15547 19.50219,-4.39047 -20.30536,1.46208 19.91337,-1.75191 -20.31906,-1.2574 19.9692,0.91791 -19.97017,-3.95445 19.66868,3.57136 -19.26491,-6.58093 19.01717,6.16107 -18.21587,-9.08997 18.0263,8.64084 -16.84175,-11.43681 16.71374,10.96642 -15.16711,-13.57955 15.10294,13.09629 -13.2218,-15.47996 13.22261,14.99246 -11.04055,-17.10413 11.10634,16.62109 -8.66229,-18.42308 8.79186,17.95312 -6.12944,-19.41327 6.32051,18.96477 -3.48722,-20.05703 3.73635,19.638 -0.78276,-20.34287 1.08553,19.96079 1.93566,-20.2657 -1.58468,19.92738 4.61955,-19.82688 -4.22659,19.53836 7.22099,-19.03425 -6.79309,18.80068 9.69358,-17.90195 -9.23837,17.72749 11.99319,-16.45019 -11.51878,16.33797 14.07878,-14.70488 -13.59365,14.65689 15.91313,-12.69715 -15.42593,12.71426 17.46351,-10.46286 -16.98293,10.54474 18.70224,-8.04184 -18.23688,8.18705 19.60725,-5.47732 -19.16538,5.68326 20.16236,-2.81506 -19.75189,3.07806 20.35767,-0.10256 -19.98591,0.41793 20.18969,2.61176 -19.86329,-2.24967 19.66144,5.27949 -19.38622,-4.87711 18.78234,7.85299 -18.56319,-7.41752 17.56804,10.28636 -17.4089,-9.82557 16.04025,12.53617 -15.94394,-12.05828 14.22622,14.56227 -14.19447,-14.07581 z"
+ d="m 306.76606,791.91313 -12.1917,-15.84216 9.87347,17.80337 -9.97137,-17.3258 7.41242,18.96052 -7.5731,-18.50027 4.81909,19.77933 -5.03968,-19.34459 2.13976,20.24516 -2.41633,-19.84371 -0.57774,20.34973 0.25013,-19.98872 -3.28494,20.09116 2.91214,-19.77704 -5.93352,19.47405 5.52217,-19.21242 -8.47622,18.50944 8.03367,-18.30497 -10.86765,17.21451 10.40181,-17.07085 -13.06517,15.6124 12.58432,-15.53212 -15.02951,13.73169 14.54226,-13.71621 -16.72567,11.60593 16.2407,-11.65553 -18.12335,9.27305 17.64932,-9.38685 -19.19762,6.77471 18.74299,-6.95068 -19.92931,4.15547 19.50219,-4.39047 -20.30536,1.46208 19.91337,-1.75191 -20.31906,-1.2574 19.9692,0.91791 -19.97017,-3.95445 19.66868,3.57136 -19.26491,-6.58093 19.01717,6.16107 -18.21587,-9.08997 18.0263,8.64084 -16.84175,-11.43681 16.71374,10.96642 -15.16711,-13.57955 15.10294,13.09629 -13.2218,-15.47996 13.22261,14.99246 -11.04055,-17.10413 11.10634,16.62109 -8.66229,-18.42308 8.79186,17.95312 -6.12944,-19.41327 6.32051,18.96477 -3.48722,-20.05703 3.73635,19.638 -0.78276,-20.34287 1.08553,19.96079 1.93566,-20.2657 -1.58468,19.92738 4.61955,-19.82688 -4.22659,19.53836 7.22099,-19.03425 -6.79309,18.80068 9.69358,-17.90195 -9.23837,17.72749 11.99319,-16.45019 -11.51878,16.33797 14.07878,-14.70488 -13.59365,14.65689 15.91313,-12.69715 -15.42593,12.71426 17.46351,-10.46286 -16.98293,10.54474 18.70224,-8.04184 -18.23688,8.18705 19.60725,-5.47732 -19.16538,5.68326 20.16236,-2.81506 -19.75189,3.07806 20.35767,-0.10256 -19.98591,0.41793 20.18969,2.61176 -19.86329,-2.24967 19.66144,5.27949 -19.38622,-4.87711 18.78234,7.85299 -18.56319,-7.41752 17.56804,10.28636 -17.4089,-9.82557 16.04025,12.53617 -15.94394,-12.05828 14.22622,14.56227 -14.19447,-14.07581 z"
id="path3138"
inkscape:connector-curvature="0" />
<g
@@ -709,5 +642,32 @@
inkscape:connector-curvature="0" />
</g>
</g>
+ <g
+ id="g3254"
+ transform="translate(338.59482,84.506185)">
+ <path
+ style="fill:#cacaca"
+ d="m -141.64871,731.31997 c -22.71912,-19.44593 -41.57543,-35.35622 -41.90292,-35.35622 -0.32748,0 -1.38939,-0.93725 -2.35979,-2.08277 -0.9704,-1.14552 -7.90154,-7.32971 -15.40255,-13.74263 -7.501,-6.41292 -13.63819,-11.94371 -13.63819,-12.29064 0,-0.88187 32.94299,-40.77529 33.63762,-40.7346 0.31135,0.0182 2.09744,1.36979 3.96908,3.00344 3.28207,2.86475 3.35476,3.04536 2.04582,5.08275 -1.35586,2.11043 -1.3229,2.14175 34.24589,32.54236 17.1942,14.70863 2.10006,2.23702 49.76002,42.17705 3.337624,3.54064 12.833354,11.65568 13.638778,11.65568 0.374084,0 1.368139,-0.635 2.209022,-1.41111 1.415168,-1.30616 1.790534,-1.19664 5.047204,1.4725 1.935081,1.58598 3.518332,3.2382 3.518332,3.6716 0,0.60316 -27.142705,34.25352 -32.452888,40.2337 -0.798338,0.89908 -9.597358,-6.21682 -42.315428,-34.22111 z m 55.643272,1.80366 c 3.369577,-4.09088 6.031292,-7.52437 5.914922,-7.62997 -0.116371,-0.1056 -3.134056,-2.6544 -6.705963,-5.66399 -3.571906,-3.00959 -7.468532,-6.32401 -8.659167,-7.36537 -18.785954,-16.43073 -83.388544,-71.25434 -83.964104,-71.25434 -0.428,0 -3.79888,3.63115 -7.49085,8.06923 l -6.71267,8.06923 2.99805,2.74906 c 6.28446,5.76252 25.34774,22.23643 27.19665,23.50251 1.06397,0.72858 7.73348,6.34831 14.82114,12.48828 45.0405,39.01819 54.37458,46.69552 55.42343,45.58612 0.578623,-0.61204 3.808977,-4.45988 7.178562,-8.55076 z m -6.845773,-7.63839 -5.621765,-4.84248 -1.594264,2.23206 c -2.83332,3.96681 -9.24307,2.0621 -9.24307,-2.74664 0,-1.96694 1.60967,-4.36691 3.25883,-4.85882 0.60173,-0.17948 -3.00265,-3.81087 -8.00973,-8.06975 -5.00708,-4.25888 -9.10377,-7.19989 -9.10377,-6.53558 0,3.85753 -6.76833,5.48036 -9.04303,2.16822 -1.84953,-2.69305 -1.69925,-3.94115 0.77882,-6.46847 l 2.1268,-2.16906 -8.81055,-7.52721 c -8.35729,-7.13998 -8.84757,-7.42514 -9.53022,-5.54308 -0.8623,2.37734 -2.17164,3.32697 -4.61231,3.34516 -4.31354,0.0322 -6.32588,-6.65891 -2.76722,-9.20103 1.16504,-0.83225 1.58826,-1.65868 1.0824,-2.11364 -0.45686,-0.41089 -3.72549,-3.24889 -7.26362,-6.30667 -6.03575,-5.21631 -6.4753,-5.4429 -7.11851,-3.66958 -0.37705,1.03952 -1.65513,2.34058 -2.84017,2.89126 -4.9528,2.30149 -9.04335,-5.04194 -4.84885,-8.70476 1.6688,-1.45726 1.60964,-1.57837 -2.69206,-5.51089 -4.33567,-3.96356 -4.37391,-4.0434 -2.68305,-5.60092 1.67653,-1.54433 2.77013,-0.6785 48.36917,38.2949 25.65962,21.93122 47.175072,40.37583 47.812101,40.98803 0.963913,0.92633 0.96529,1.42821 0.0078,2.99122 -0.632534,1.03298 -1.348578,1.86061 -1.591208,1.83918 -0.24263,-0.0215 -2.970934,-2.21808 -6.062915,-4.88145 z m -36.808149,23.46605 c -0.29434,-0.48572 -0.12251,-0.88313 0.38185,-0.88313 0.50437,0 0.91703,0.39741 0.91703,0.88313 0,0.48572 -0.17183,0.88312 -0.38185,0.88312 -0.21002,0 -0.62268,-0.3974 -0.91703,-0.88312 z"
+ id="path3262"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ssssscssccsssssssssssscsssssccssssssscsscsssssssssscccccsssc" />
+ <path
+ style="fill:#084af1"
+ d="m -141.70294,730.79802 c -19.70363,-14.08884 -39.13144,-33.87071 -55.75597,-47.91474 -6.52563,-5.49424 -13.14755,-11.1008 -14.71536,-12.45902 l -2.85057,-2.46949 16.61467,-20.21663 c 9.13806,-11.11914 16.69487,-20.32309 16.79289,-20.45321 0.098,-0.13012 1.7884,1.2608 3.7564,3.09094 l 3.57817,3.32752 -9.94372,11.87508 c -5.46905,6.53129 -9.94372,11.95688 -9.94372,12.05686 0,0.1 5.57145,4.93405 12.381,10.74237 6.80956,5.80833 13.49072,11.60947 14.84703,12.89144 26.78141,21.10707 22.69793,19.28577 46.45645,39.59158 l 26.492029,22.6407 9.697878,-11.84664 c 5.333839,-6.51565 10.005573,-11.84664 10.381649,-11.84664 0.376067,0 2.105823,1.29157 3.843891,2.87016 l 3.160128,2.87016 -16.400307,19.85766 c -9.020177,10.92171 -16.709328,19.94057 -17.087018,20.04191 -0.37767,0.10135 -18.96517,-15.49116 -41.30552,-34.65001 z m 56.268003,14.46643 c 8.061849,-9.79926 14.937938,-18.28594 15.280192,-18.85928 0.352246,-0.59009 -0.262676,-1.89033 -1.417082,-2.99639 l -2.039355,-1.95396 -9.745494,11.7612 c -5.360025,6.46867 -10.222295,11.71497 -10.805048,11.65847 -0.582753,-0.0565 -16.544136,-13.36963 -35.469746,-29.58471 -18.94546,-13.73014 -37.5743,-32.11549 -53.48048,-45.78046 l -13.62042,-11.67063 9.94399,-12.04378 9.944,-12.04379 -2.19523,-2.23168 c -1.43393,-1.45773 -2.41119,-1.89629 -2.81795,-1.26459 -0.3425,0.53189 -7.40344,9.19475 -15.69099,19.25079 -8.28755,10.05604 -14.71698,18.59076 -14.28763,18.96604 0.42936,0.37529 5.65143,4.84671 11.60461,9.9365 5.95318,5.08979 18.03271,15.42525 26.84342,22.96768 56.51704,48.38165 72.22034,61.70544 72.72547,61.70544 0.3134,0 7.165885,-8.01758 15.227743,-17.81685 z m -7.855917,-20.58612 c -2.857526,-2.64073 -5.445508,-4.81682 -5.751064,-4.83576 -0.305565,-0.0189 -0.798575,0.95304 -1.095582,2.15994 -0.61291,2.49054 -4.28466,3.8934 -6.49261,2.48061 -0.75973,-0.48613 -1.76306,-1.97694 -2.22962,-3.31291 -0.73489,-2.1043 -0.53626,-2.70279 1.48574,-4.4766 l 2.33403,-2.04754 -8.8211,-7.57633 -8.8211,-7.57634 -1.12922,2.19802 c -2.56146,4.98588 -9.24388,3.01172 -8.70422,-2.57147 0.16368,-1.69349 0.94934,-3.02345 2.1421,-3.62616 1.7596,-0.88914 1.26079,-1.48573 -7.57677,-9.06202 -7.2849,-6.24522 -9.46038,-7.71108 -9.46038,-6.37449 0,2.27319 -3.71861,4.74263 -6.01994,3.9977 -3.90318,-1.26344 -4.44878,-7.77734 -0.76774,-9.1661 1.62055,-0.6114 0.97197,-1.42003 -5.92672,-7.38933 l -7.74641,-6.7028 -0.95129,2.57037 c -0.80454,2.17381 -1.42577,2.57036 -4.02676,2.57036 -4.95501,0 -6.78966,-5.7403 -2.70668,-8.46874 l 2.16155,-1.44445 -4.32634,-3.58926 c -4.4612,-3.70114 -5.1153,-5.04226 -3.23534,-6.63349 0.99717,-0.84403 17.71344,13.13391 94.466073,78.99136 2.027856,1.74 2.280608,2.35424 1.409323,3.42494 -1.653165,2.03152 -2.643601,1.60452 -8.20993,-3.53951 z"
+ id="path3260"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccscscscssscccssscsccssscsscccccscssssssscsssscccsssssssscssscsssss" />
+ <path
+ style="fill:#686868"
+ d="m -141.70294,730.79802 c -19.70363,-14.08884 -39.13144,-33.87071 -55.75597,-47.91474 -6.52563,-5.49424 -13.14755,-11.1008 -14.71536,-12.45902 l -2.85057,-2.46949 16.61467,-20.21663 c 9.13806,-11.11914 16.69487,-20.32309 16.79289,-20.45321 0.098,-0.13012 1.7884,1.2608 3.7564,3.09094 l 3.57817,3.32752 -9.94372,11.87508 c -5.46905,6.53129 -9.94372,11.95688 -9.94372,12.05686 0,0.1 5.57145,4.93405 12.381,10.74237 6.80956,5.80833 13.49072,11.60947 14.84703,12.89144 26.78141,21.10707 22.69793,19.28577 46.45645,39.59158 l 26.492029,22.6407 9.697878,-11.84664 c 5.333839,-6.51565 10.005573,-11.84664 10.381649,-11.84664 0.376067,0 2.105823,1.29157 3.843891,2.87016 l 3.160128,2.87016 -16.400307,19.85766 c -9.020177,10.92171 -16.709328,19.94057 -17.087018,20.04191 -0.37767,0.10135 -18.96517,-15.49116 -41.30552,-34.65001 z m 56.268003,14.46643 c 8.061849,-9.79926 14.937938,-18.28594 15.280192,-18.85928 0.352246,-0.59009 -0.262676,-1.89033 -1.417082,-2.99639 l -2.039355,-1.95396 -9.745494,11.7612 c -5.360025,6.46867 -10.222295,11.71497 -10.805048,11.65847 -0.582753,-0.0565 -16.544136,-13.36963 -35.469746,-29.58471 -18.94546,-13.73014 -37.5743,-32.11549 -53.48048,-45.78046 l -13.62042,-11.67063 9.94399,-12.04378 9.944,-12.04379 -2.19523,-2.23168 c -1.43393,-1.45773 -2.41119,-1.89629 -2.81795,-1.26459 -0.3425,0.53189 -7.40344,9.19475 -15.69099,19.25079 -8.28755,10.05604 -14.71698,18.59076 -14.28763,18.96604 0.42936,0.37529 5.65143,4.84671 11.60461,9.9365 5.95318,5.08979 18.03271,15.42525 26.84342,22.96768 56.51704,48.38165 72.22034,61.70544 72.72547,61.70544 0.3134,0 7.165885,-8.01758 15.227743,-17.81685 z m -7.855917,-20.58612 c -2.857526,-2.64073 -5.445508,-4.81682 -5.751064,-4.83576 -0.305565,-0.0189 -0.798575,0.95304 -1.095582,2.15994 -0.61291,2.49054 -4.28466,3.8934 -6.49261,2.48061 -0.75973,-0.48613 -1.76306,-1.97694 -2.22962,-3.31291 -0.73489,-2.1043 -0.53626,-2.70279 1.48574,-4.4766 l 2.33403,-2.04754 -8.8211,-7.57633 -8.8211,-7.57634 -1.12922,2.19802 c -2.56146,4.98588 -9.24388,3.01172 -8.70422,-2.57147 0.16368,-1.69349 0.94934,-3.02345 2.1421,-3.62616 1.7596,-0.88914 1.26079,-1.48573 -7.57677,-9.06202 -7.2849,-6.24522 -9.46038,-7.71108 -9.46038,-6.37449 0,2.27319 -3.71861,4.74263 -6.01994,3.9977 -3.90318,-1.26344 -4.44878,-7.77734 -0.76774,-9.1661 1.62055,-0.6114 0.97197,-1.42003 -5.92672,-7.38933 l -7.74641,-6.7028 -0.95129,2.57037 c -0.80454,2.17381 -1.42577,2.57036 -4.02676,2.57036 -4.95501,0 -6.78966,-5.7403 -2.70668,-8.46874 l 2.16155,-1.44445 -4.32634,-3.58926 c -4.4612,-3.70114 -5.1153,-5.04226 -3.23534,-6.63349 0.99717,-0.84403 17.71344,13.13391 94.466073,78.99136 2.027856,1.74 2.280608,2.35424 1.409323,3.42494 -1.653165,2.03152 -2.643601,1.60452 -8.20993,-3.53951 z m -9.126616,-2.61999 c 1.39088,-1.70921 0.31669,-4.89958 -1.64967,-4.89958 -2.4706,0 -3.81387,2.18896 -2.67505,4.35918 1.11901,2.13243 2.85289,2.34909 4.32472,0.5404 z m -23.84179,-20.4156 c 1.86378,-1.90082 0.27164,-5.01365 -2.36745,-4.62868 -2.17675,0.31754 -2.94808,2.86824 -1.43108,4.73243 1.33185,1.63667 2.11294,1.61534 3.79853,-0.10375 z m -23.31618,-22.45838 c 0,-1.72542 -0.49612,-2.26649 -2.27066,-2.47637 -2.43692,-0.28822 -3.69168,1.44456 -2.78705,3.84883 0.32712,0.8694 1.34869,1.27403 2.78705,1.10391 1.77454,-0.20988 2.27066,-0.75094 2.27066,-2.47637 z m -20.78446,-16.77148 c 0.7387,-2.3737 -0.11655,-3.54041 -2.59529,-3.54041 -2.47874,0 -3.334,1.16671 -2.5953,3.54041 0.3432,1.1028 1.31077,1.75835 2.5953,1.75835 1.28452,0 2.25209,-0.65555 2.59529,-1.75835 z"
+ id="path3258"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccscscscssscccssscsccssscsscccccscssssssscsssscccsssssssscssscsssssssssssssssssssssss" />
+ <path
+ style="fill:#050606"
+ d="m -93.290854,724.21682 c -5.650575,-4.88726 -6.093301,-5.11007 -6.531783,-3.28723 -0.258703,1.07545 -1.424043,2.44028 -2.589643,3.03294 -2.87198,1.46029 -5.50687,-0.32662 -5.86645,-3.97847 -0.21233,-2.15635 0.18365,-2.95556 1.92559,-3.88638 2.1918,-1.17123 2.1882,-1.17583 -7.2792,-9.29207 l -9.47209,-8.12026 -1.11907,2.39248 c -0.7513,1.60623 -1.91675,2.48601 -3.54631,2.67708 -4.93352,0.57846 -6.72744,-4.44693 -2.7317,-7.65245 l 2.18856,-1.75573 -9.30755,-8.03849 c -8.79076,-7.59217 -9.34738,-7.92868 -10.02494,-6.06065 -1.42821,3.93754 -5.85089,4.60031 -8.033,1.20381 -1.61808,-2.51858 -0.57089,-5.46204 2.333,-6.55761 1.51187,-0.57039 0.67241,-1.56294 -6.27773,-7.42256 l -8.02298,-6.76412 -1.5594,2.61518 c -1.97838,3.31784 -5.29108,3.52331 -7.26516,0.45061 -1.6479,-2.56499 -0.99967,-5.4643 1.39502,-6.23945 2.48539,-0.80452 2.14176,-1.52638 -2.71475,-5.70283 -3.85706,-3.31696 -4.2459,-3.94533 -3.13961,-5.07361 1.1063,-1.12828 6.98696,3.60455 47.48165,38.21383 25.42043,21.72589 46.789541,40.04177 47.486916,40.70196 1.113318,1.05396 1.113318,1.35805 0,2.49349 -1.113326,1.13543 -2.00716,0.65379 -7.32937,-3.94947 z m -9.126616,-2.15848 c 1.39088,-1.70921 0.31669,-4.89958 -1.64967,-4.89958 -2.4706,0 -3.81387,2.18896 -2.67505,4.35918 1.11901,2.13243 2.85289,2.34909 4.32472,0.5404 z m -23.84179,-20.4156 c 1.86378,-1.90082 0.27164,-5.01365 -2.36745,-4.62868 -2.17675,0.31754 -2.94808,2.86824 -1.43108,4.73243 1.33185,1.63667 2.11294,1.61534 3.79853,-0.10375 z m -23.31618,-22.45838 c 0,-1.72542 -0.49612,-2.26649 -2.27066,-2.47637 -2.43692,-0.28822 -3.69168,1.44456 -2.78705,3.84883 0.32712,0.8694 1.34869,1.27403 2.78705,1.10391 1.77454,-0.20988 2.27066,-0.75094 2.27066,-2.47637 z m -20.78446,-16.77148 c 0.7387,-2.3737 -0.11655,-3.54041 -2.59529,-3.54041 -2.47874,0 -3.334,1.16671 -2.5953,3.54041 0.3432,1.1028 1.31077,1.75835 2.5953,1.75835 1.28452,0 2.25209,-0.65555 2.59529,-1.75835 z"
+ id="path3256"
+ inkscape:connector-curvature="0" />
+ </g>
</g>
</svg>
diff --git a/ebus/webapp/static/lib/d3-v2.6.1/d3.time.js b/ebus/webapp/static/lib/d3-v2.6.1/d3.time.js
new file mode 100644
index 0000000..4c1cda4
--- /dev/null
+++ b/ebus/webapp/static/lib/d3-v2.6.1/d3.time.js
@@ -0,0 +1,687 @@
+(function(){d3.time = {};
+
+var d3_time = Date;
+d3.time.format = function(template) {
+ var n = template.length;
+
+ function format(date) {
+ var string = [],
+ i = -1,
+ j = 0,
+ c,
+ f;
+ while (++i < n) {
+ if (template.charCodeAt(i) == 37) {
+ string.push(
+ template.substring(j, i),
+ (f = d3_time_formats[c = template.charAt(++i)])
+ ? f(date) : c);
+ j = i + 1;
+ }
+ }
+ string.push(template.substring(j, i));
+ return string.join("");
+ }
+
+ format.parse = function(string) {
+ var date = new d3_time(1900, 0, 1),
+ i = d3_time_parse(date, template, string, 0);
+ if (i != string.length) return null;
+ if (date.hour12) {
+ var hours = date.getHours() % 12;
+ date.setHours(date.hour12pm ? hours + 12 : hours);
+ }
+ delete date.hour12;
+ delete date.hour12pm;
+ return date;
+ };
+
+ format.toString = function() {
+ return template;
+ };
+
+ return format;
+};
+
+function d3_time_parse(date, template, string, j) {
+ var c,
+ p,
+ i = 0,
+ n = template.length,
+ m = string.length;
+ while (i < n) {
+ if (j >= m) return -1;
+ c = template.charCodeAt(i++);
+ if (c == 37) {
+ p = d3_time_parsers[template.charAt(i++)];
+ if (!p || ((j = p(date, string, j)) < 0)) return -1;
+ } else if (c != string.charCodeAt(j++)) {
+ return -1;
+ }
+ }
+ return j;
+}
+
+var d3_time_zfill2 = d3.format("02d"),
+ d3_time_zfill3 = d3.format("03d"),
+ d3_time_zfill4 = d3.format("04d"),
+ d3_time_sfill2 = d3.format("2d");
+
+var d3_time_formats = {
+ a: function(d) { return d3_time_weekdays[d.getDay()].substring(0, 3); },
+ A: function(d) { return d3_time_weekdays[d.getDay()]; },
+ b: function(d) { return d3_time_months[d.getMonth()].substring(0, 3); },
+ B: function(d) { return d3_time_months[d.getMonth()]; },
+ c: d3.time.format("%a %b %e %H:%M:%S %Y"),
+ d: function(d) { return d3_time_zfill2(d.getDate()); },
+ e: function(d) { return d3_time_sfill2(d.getDate()); },
+ H: function(d) { return d3_time_zfill2(d.getHours()); },
+ I: function(d) { return d3_time_zfill2(d.getHours() % 12 || 12); },
+ j: d3_time_dayOfYear,
+ L: function(d) { return d3_time_zfill3(d.getMilliseconds()); },
+ m: function(d) { return d3_time_zfill2(d.getMonth() + 1); },
+ M: function(d) { return d3_time_zfill2(d.getMinutes()); },
+ p: function(d) { return d.getHours() >= 12 ? "PM" : "AM"; },
+ S: function(d) { return d3_time_zfill2(d.getSeconds()); },
+ U: d3_time_weekNumberSunday,
+ w: function(d) { return d.getDay(); },
+ W: d3_time_weekNumberMonday,
+ x: d3.time.format("%m/%d/%y"),
+ X: d3.time.format("%H:%M:%S"),
+ y: function(d) { return d3_time_zfill2(d.getFullYear() % 100); },
+ Y: function(d) { return d3_time_zfill4(d.getFullYear() % 10000); },
+ Z: d3_time_zone,
+ "%": function(d) { return "%"; }
+};
+
+var d3_time_parsers = {
+ a: d3_time_parseWeekdayAbbrev,
+ A: d3_time_parseWeekday,
+ b: d3_time_parseMonthAbbrev,
+ B: d3_time_parseMonth,
+ c: d3_time_parseLocaleFull,
+ d: d3_time_parseDay,
+ e: d3_time_parseDay,
+ H: d3_time_parseHour24,
+ I: d3_time_parseHour12,
+ // j: function(d, s, i) { /*TODO day of year [001,366] */ return i; },
+ L: d3_time_parseMilliseconds,
+ m: d3_time_parseMonthNumber,
+ M: d3_time_parseMinutes,
+ p: d3_time_parseAmPm,
+ S: d3_time_parseSeconds,
+ // U: function(d, s, i) { /*TODO week number (sunday) [00,53] */ return i; },
+ // w: function(d, s, i) { /*TODO weekday [0,6] */ return i; },
+ // W: function(d, s, i) { /*TODO week number (monday) [00,53] */ return i; },
+ x: d3_time_parseLocaleDate,
+ X: d3_time_parseLocaleTime,
+ y: d3_time_parseYear,
+ Y: d3_time_parseFullYear
+ // ,
+ // Z: function(d, s, i) { /*TODO time zone */ return i; },
+ // "%": function(d, s, i) { /*TODO literal % */ return i; }
+};
+
+// Note: weekday is validated, but does not set the date.
+function d3_time_parseWeekdayAbbrev(date, string, i) {
+ return string.substring(i, i += 3).toLowerCase() in d3_time_weekdayAbbrevLookup ? i : -1;
+}
+
+var d3_time_weekdayAbbrevLookup = {
+ sun: 3,
+ mon: 3,
+ tue: 3,
+ wed: 3,
+ thu: 3,
+ fri: 3,
+ sat: 3
+};
+
+// Note: weekday is validated, but does not set the date.
+function d3_time_parseWeekday(date, string, i) {
+ d3_time_weekdayRe.lastIndex = 0;
+ var n = d3_time_weekdayRe.exec(string.substring(i, i + 10));
+ return n ? i += n[0].length : -1;
+}
+
+var d3_time_weekdayRe = /^(?:Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday)/ig;
+
+var d3_time_weekdays = [
+ "Sunday",
+ "Monday",
+ "Tuesday",
+ "Wednesday",
+ "Thursday",
+ "Friday",
+ "Saturday"
+];
+
+function d3_time_parseMonthAbbrev(date, string, i) {
+ var n = d3_time_monthAbbrevLookup[string.substring(i, i += 3).toLowerCase()];
+ return n == null ? -1 : (date.setMonth(n), i);
+}
+
+var d3_time_monthAbbrevLookup = {
+ jan: 0,
+ feb: 1,
+ mar: 2,
+ apr: 3,
+ may: 4,
+ jun: 5,
+ jul: 6,
+ aug: 7,
+ sep: 8,
+ oct: 9,
+ nov: 10,
+ dec: 11
+};
+
+function d3_time_parseMonth(date, string, i) {
+ d3_time_monthRe.lastIndex = 0;
+ var n = d3_time_monthRe.exec(string.substring(i, i + 12));
+ return n ? (date.setMonth(d3_time_monthLookup[n[0].toLowerCase()]), i += n[0].length) : -1;
+}
+
+var d3_time_monthRe = /^(?:January|February|March|April|May|June|July|August|September|October|November|December)/ig;
+
+var d3_time_monthLookup = {
+ january: 0,
+ february: 1,
+ march: 2,
+ april: 3,
+ may: 4,
+ june: 5,
+ july: 6,
+ august: 7,
+ september: 8,
+ october: 9,
+ november: 10,
+ december: 11
+};
+
+var d3_time_months = [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December"
+];
+
+function d3_time_parseLocaleFull(date, string, i) {
+ return d3_time_parse(date, d3_time_formats.c.toString(), string, i);
+}
+
+function d3_time_parseLocaleDate(date, string, i) {
+ return d3_time_parse(date, d3_time_formats.x.toString(), string, i);
+}
+
+function d3_time_parseLocaleTime(date, string, i) {
+ return d3_time_parse(date, d3_time_formats.X.toString(), string, i);
+}
+
+function d3_time_parseFullYear(date, string, i) {
+ d3_time_numberRe.lastIndex = 0;
+ var n = d3_time_numberRe.exec(string.substring(i, i + 4));
+ return n ? (date.setFullYear(n[0]), i += n[0].length) : -1;
+}
+
+function d3_time_parseYear(date, string, i) {
+ d3_time_numberRe.lastIndex = 0;
+ var n = d3_time_numberRe.exec(string.substring(i, i + 2));
+ return n ? (date.setFullYear(d3_time_century() + +n[0]), i += n[0].length) : -1;
+}
+
+function d3_time_century() {
+ return ~~(new Date().getFullYear() / 1000) * 1000;
+}
+
+function d3_time_parseMonthNumber(date, string, i) {
+ d3_time_numberRe.lastIndex = 0;
+ var n = d3_time_numberRe.exec(string.substring(i, i + 2));
+ return n ? (date.setMonth(n[0] - 1), i += n[0].length) : -1;
+}
+
+function d3_time_parseDay(date, string, i) {
+ d3_time_numberRe.lastIndex = 0;
+ var n = d3_time_numberRe.exec(string.substring(i, i + 2));
+ return n ? (date.setDate(+n[0]), i += n[0].length) : -1;
+}
+
+// Note: we don't validate that the hour is in the range [0,23].
+function d3_time_parseHour24(date, string, i) {
+ d3_time_numberRe.lastIndex = 0;
+ var n = d3_time_numberRe.exec(string.substring(i, i + 2));
+ return n ? (date.setHours(+n[0]), i += n[0].length) : -1;
+}
+
+// Note: we don't validate that the hour is in the range [1,12].
+function d3_time_parseHour12(date, string, i) {
+ date.hour12 = true;
+ return d3_time_parseHour24(date, string, i);
+}
+
+function d3_time_parseMinutes(date, string, i) {
+ d3_time_numberRe.lastIndex = 0;
+ var n = d3_time_numberRe.exec(string.substring(i, i + 2));
+ return n ? (date.setMinutes(+n[0]), i += n[0].length) : -1;
+}
+
+function d3_time_parseSeconds(date, string, i) {
+ d3_time_numberRe.lastIndex = 0;
+ var n = d3_time_numberRe.exec(string.substring(i, i + 2));
+ return n ? (date.setSeconds(+n[0]), i += n[0].length) : -1;
+}
+
+function d3_time_parseMilliseconds(date, string, i) {
+ d3_time_numberRe.lastIndex = 0;
+ var n = d3_time_numberRe.exec(string.substring(i, i + 3));
+ return n ? (date.setMilliseconds(+n[0]), i += n[0].length) : -1;
+}
+
+// Note: we don't look at the next directive.
+var d3_time_numberRe = /\s*\d+/;
+
+function d3_time_parseAmPm(date, string, i) {
+ var n = d3_time_amPmLookup[string.substring(i, i += 2).toLowerCase()];
+ return n == null ? -1 : (date.hour12pm = n, i);
+}
+
+var d3_time_amPmLookup = {
+ am: 0,
+ pm: 1
+};
+
+function d3_time_year(d) {
+ return new d3_time(d.getFullYear(), 0, 1);
+}
+
+function d3_time_daysElapsed(d0, d1) {
+ return ~~((d1 - d0) / 864e5 - (d1.getTimezoneOffset() - d0.getTimezoneOffset()) / 1440);
+}
+
+function d3_time_dayOfYear(d) {
+ return d3_time_zfill3(1 + d3_time_daysElapsed(d3_time_year(d), d));
+}
+
+function d3_time_weekNumberSunday(d) {
+ var d0 = d3_time_year(d);
+ return d3_time_zfill2(~~((d3_time_daysElapsed(d0, d) + d0.getDay()) / 7));
+}
+
+function d3_time_weekNumberMonday(d) {
+ var d0 = d3_time_year(d);
+ return d3_time_zfill2(~~((d3_time_daysElapsed(d0, d) + (d0.getDay() + 6) % 7) / 7));
+}
+
+// TODO table of time zone offset names?
+function d3_time_zone(d) {
+ var z = d.getTimezoneOffset(),
+ zs = z > 0 ? "-" : "+",
+ zh = ~~(Math.abs(z) / 60),
+ zm = Math.abs(z) % 60;
+ return zs + d3_time_zfill2(zh) + d3_time_zfill2(zm);
+}
+d3.time.format.utc = function(template) {
+ var local = d3.time.format(template);
+
+ function format(date) {
+ try {
+ d3_time = d3_time_format_utc;
+ var utc = new d3_time();
+ utc._ = date;
+ return local(utc);
+ } finally {
+ d3_time = Date;
+ }
+ }
+
+ format.parse = function(string) {
+ try {
+ d3_time = d3_time_format_utc;
+ var date = local.parse(string);
+ return date && date._;
+ } finally {
+ d3_time = Date;
+ }
+ };
+
+ format.toString = local.toString;
+
+ return format;
+};
+
+function d3_time_format_utc() {
+ this._ = new Date(Date.UTC.apply(this, arguments));
+}
+
+d3_time_format_utc.prototype = {
+ getDate: function() { return this._.getUTCDate(); },
+ getDay: function() { return this._.getUTCDay(); },
+ getFullYear: function() { return this._.getUTCFullYear(); },
+ getHours: function() { return this._.getUTCHours(); },
+ getMilliseconds: function() { return this._.getUTCMilliseconds(); },
+ getMinutes: function() { return this._.getUTCMinutes(); },
+ getMonth: function() { return this._.getUTCMonth(); },
+ getSeconds: function() { return this._.getUTCSeconds(); },
+ getTimezoneOffset: function() { return 0; },
+ valueOf: function() { return this._.getTime(); },
+ setDate: function(x) { this._.setUTCDate(x); },
+ setDay: function(x) { this._.setUTCDay(x); },
+ setFullYear: function(x) { this._.setUTCFullYear(x); },
+ setHours: function(x) { this._.setUTCHours(x); },
+ setMilliseconds: function(x) { this._.setUTCMilliseconds(x); },
+ setMinutes: function(x) { this._.setUTCMinutes(x); },
+ setMonth: function(x) { this._.setUTCMonth(x); },
+ setSeconds: function(x) { this._.setUTCSeconds(x); }
+};
+var d3_time_formatIso = d3.time.format.utc("%Y-%m-%dT%H:%M:%S.%LZ");
+
+d3.time.format.iso = Date.prototype.toISOString ? d3_time_formatIsoNative : d3_time_formatIso;
+
+function d3_time_formatIsoNative(date) {
+ return date.toISOString();
+}
+
+d3_time_formatIsoNative.parse = function(string) {
+ return new Date(string);
+};
+
+d3_time_formatIsoNative.toString = d3_time_formatIso.toString;
+function d3_time_range(floor, step, number) {
+ return function(t0, t1, dt) {
+ var time = floor(t0), times = [];
+ if (time < t0) step(time);
+ if (dt > 1) {
+ while (time < t1) {
+ var date = new Date(+time);
+ if (!(number(date) % dt)) times.push(date);
+ step(time);
+ }
+ } else {
+ while (time < t1) times.push(new Date(+time)), step(time);
+ }
+ return times;
+ };
+}
+d3.time.second = function(date) {
+ return new Date(~~(date / 1e3) * 1e3);
+};
+
+d3.time.second.utc = d3.time.second;
+d3.time.seconds = d3_time_range(d3.time.second, function(date) {
+ date.setTime(date.getTime() + 1e3);
+}, function(date) {
+ return date.getSeconds();
+});
+
+d3.time.seconds.utc = d3.time.seconds;
+d3.time.minute = function(date) {
+ return new Date(~~(date / 6e4) * 6e4);
+};
+
+d3.time.minute.utc = d3.time.minute;d3.time.minutes = d3_time_range(d3.time.minute, d3_time_minutesStep, function(date) {
+ return date.getMinutes();
+});
+
+d3.time.minutes.utc = d3_time_range(d3.time.minute, d3_time_minutesStep, function(date) {
+ return date.getUTCMinutes();
+});
+
+function d3_time_minutesStep(date) {
+ date.setTime(date.getTime() + 6e4); // assumes no leap seconds
+}
+d3.time.hour = function(date) {
+ var offset = date.getTimezoneOffset() / 60;
+ return new Date((~~(date / 36e5 - offset) + offset) * 36e5);
+};
+
+d3.time.hour.utc = function(date) {
+ return new Date(~~(date / 36e5) * 36e5);
+};
+d3.time.hours = d3_time_range(d3.time.hour, d3_time_hoursStep, function(date) {
+ return date.getHours();
+});
+
+d3.time.hours.utc = d3_time_range(d3.time.hour.utc, d3_time_hoursStep, function(date) {
+ return date.getUTCHours();
+});
+
+function d3_time_hoursStep(date) {
+ date.setTime(date.getTime() + 36e5);
+}
+d3.time.day = function(date) {
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate());
+};
+
+d3.time.day.utc = function(date) {
+ return new Date(~~(date / 864e5) * 864e5);
+};
+d3.time.days = d3_time_range(d3.time.day, function(date) {
+ date.setDate(date.getDate() + 1);
+}, function(date) {
+ return date.getDate() - 1;
+});
+
+d3.time.days.utc = d3_time_range(d3.time.day.utc, function(date) {
+ date.setUTCDate(date.getUTCDate() + 1);
+}, function(date) {
+ return date.getUTCDate() - 1;
+});
+d3.time.week = function(date) {
+ (date = d3.time.day(date)).setDate(date.getDate() - date.getDay());
+ return date;
+};
+
+d3.time.week.utc = function(date) {
+ (date = d3.time.day.utc(date)).setUTCDate(date.getUTCDate() - date.getUTCDay());
+ return date;
+};
+d3.time.weeks = d3_time_range(d3.time.week, function(date) {
+ date.setDate(date.getDate() + 7);
+}, function(date) {
+ return ~~((date - new Date(date.getFullYear(), 0, 1)) / 6048e5);
+});
+
+d3.time.weeks.utc = d3_time_range(d3.time.week.utc, function(date) {
+ date.setUTCDate(date.getUTCDate() + 7);
+}, function(date) {
+ return ~~((date - Date.UTC(date.getUTCFullYear(), 0, 1)) / 6048e5);
+});
+d3.time.month = function(date) {
+ return new Date(date.getFullYear(), date.getMonth(), 1);
+};
+
+d3.time.month.utc = function(date) {
+ return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), 1));
+};
+d3.time.months = d3_time_range(d3.time.month, function(date) {
+ date.setMonth(date.getMonth() + 1);
+}, function(date) {
+ return date.getMonth();
+});
+
+d3.time.months.utc = d3_time_range(d3.time.month.utc, function(date) {
+ date.setUTCMonth(date.getUTCMonth() + 1);
+}, function(date) {
+ return date.getUTCMonth();
+});
+d3.time.year = function(date) {
+ return new Date(date.getFullYear(), 0, 1);
+};
+
+d3.time.year.utc = function(date) {
+ return new Date(Date.UTC(date.getUTCFullYear(), 0, 1));
+};
+d3.time.years = d3_time_range(d3.time.year, function(date) {
+ date.setFullYear(date.getFullYear() + 1);
+}, function(date) {
+ return date.getFullYear();
+});
+
+d3.time.years.utc = d3_time_range(d3.time.year.utc, function(date) {
+ date.setUTCFullYear(date.getUTCFullYear() + 1);
+}, function(date) {
+ return date.getUTCFullYear();
+});
+// TODO nice
+function d3_time_scale(linear, methods, format) {
+
+ function scale(x) {
+ return linear(x);
+ }
+
+ scale.invert = function(x) {
+ return d3_time_scaleDate(linear.invert(x));
+ };
+
+ scale.domain = function(x) {
+ if (!arguments.length) return linear.domain().map(d3_time_scaleDate);
+ linear.domain(x);
+ return scale;
+ };
+
+ scale.ticks = function(m, k) {
+ var extent = d3_time_scaleExtent(scale.domain());
+ if (typeof m !== "function") {
+ var span = extent[1] - extent[0],
+ target = span / m,
+ i = d3.bisect(d3_time_scaleSteps, target, 1, d3_time_scaleSteps.length - 1);
+ if (Math.log(target / d3_time_scaleSteps[i - 1]) < Math.log(d3_time_scaleSteps[i] / target)) --i;
+ m = methods[i];
+ k = m[1];
+ m = m[0];
+ }
+ return m(extent[0], extent[1], k);
+ };
+
+ scale.tickFormat = function() {
+ return format;
+ };
+
+ scale.copy = function() {
+ return d3_time_scale(linear.copy(), methods, format);
+ };
+
+ // TOOD expose d3_scale_linear_rebind?
+ return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp");
+}
+
+// TODO expose d3_scaleExtent?
+function d3_time_scaleExtent(domain) {
+ var start = domain[0], stop = domain[domain.length - 1];
+ return start < stop ? [start, stop] : [stop, start];
+}
+
+function d3_time_scaleDate(t) {
+ return new Date(t);
+}
+
+function d3_time_scaleFormat(formats) {
+ return function(date) {
+ var i = formats.length - 1, f = formats[i];
+ while (!f[1](date)) f = formats[--i];
+ return f[0](date);
+ };
+}
+
+var d3_time_scaleSteps = [
+ 1e3, // 1-second
+ 5e3, // 5-second
+ 15e3, // 15-second
+ 3e4, // 30-second
+ 6e4, // 1-minute
+ 3e5, // 5-minute
+ 9e5, // 15-minute
+ 18e5, // 30-minute
+ 36e5, // 1-hour
+ 108e5, // 3-hour
+ 216e5, // 6-hour
+ 432e5, // 12-hour
+ 864e5, // 1-day
+ 1728e5, // 2-day
+ 6048e5, // 1-week
+ 1728e6, // 1-month
+ 7776e6, // 3-month
+ 31536e6 // 1-year
+];
+
+var d3_time_scaleLocalMethods = [
+ [d3.time.seconds, 1],
+ [d3.time.seconds, 5],
+ [d3.time.seconds, 15],
+ [d3.time.seconds, 30],
+ [d3.time.minutes, 1],
+ [d3.time.minutes, 5],
+ [d3.time.minutes, 15],
+ [d3.time.minutes, 30],
+ [d3.time.hours, 1],
+ [d3.time.hours, 3],
+ [d3.time.hours, 6],
+ [d3.time.hours, 12],
+ [d3.time.days, 1],
+ [d3.time.days, 2],
+ [d3.time.weeks, 1],
+ [d3.time.months, 1],
+ [d3.time.months, 3],
+ [d3.time.years, 1]
+];
+
+var d3_time_scaleLocalFormats = [
+ [d3.time.format("%Y"), function(d) { return true; }],
+ [d3.time.format("%B"), function(d) { return d.getMonth(); }],
+ [d3.time.format("%b %d"), function(d) { return d.getDate() != 1; }],
+ [d3.time.format("%a %d"), function(d) { return d.getDay() && d.getDate() != 1; }],
+ [d3.time.format("%I %p"), function(d) { return d.getHours(); }],
+ [d3.time.format("%I:%M"), function(d) { return d.getMinutes(); }],
+ [d3.time.format(":%S"), function(d) { return d.getSeconds() || d.getMilliseconds(); }]
+];
+
+var d3_time_scaleLocalFormat = d3_time_scaleFormat(d3_time_scaleLocalFormats);
+
+d3.time.scale = function() {
+ return d3_time_scale(d3.scale.linear(), d3_time_scaleLocalMethods, d3_time_scaleLocalFormat);
+};
+var d3_time_scaleUTCMethods = [
+ [d3.time.seconds.utc, 1],
+ [d3.time.seconds.utc, 5],
+ [d3.time.seconds.utc, 15],
+ [d3.time.seconds.utc, 30],
+ [d3.time.minutes.utc, 1],
+ [d3.time.minutes.utc, 5],
+ [d3.time.minutes.utc, 15],
+ [d3.time.minutes.utc, 30],
+ [d3.time.hours.utc, 1],
+ [d3.time.hours.utc, 3],
+ [d3.time.hours.utc, 6],
+ [d3.time.hours.utc, 12],
+ [d3.time.days.utc, 1],
+ [d3.time.days.utc, 2],
+ [d3.time.weeks.utc, 1],
+ [d3.time.months.utc, 1],
+ [d3.time.months.utc, 3],
+ [d3.time.years.utc, 1]
+];
+
+var d3_time_scaleUTCFormats = [
+ [d3.time.format.utc("%Y"), function(d) { return true; }],
+ [d3.time.format.utc("%B"), function(d) { return d.getUTCMonth(); }],
+ [d3.time.format.utc("%b %d"), function(d) { return d.getUTCDate() != 1; }],
+ [d3.time.format.utc("%a %d"), function(d) { return d.getUTCDay() && d.getUTCDate() != 1; }],
+ [d3.time.format.utc("%I %p"), function(d) { return d.getUTCHours(); }],
+ [d3.time.format.utc("%I:%M"), function(d) { return d.getUTCMinutes(); }],
+ [d3.time.format.utc(":%S"), function(d) { return d.getUTCSeconds() || d.getUTCMilliseconds(); }]
+];
+
+var d3_time_scaleUTCFormat = d3_time_scaleFormat(d3_time_scaleUTCFormats);
+
+d3.time.scale.utc = function() {
+ return d3_time_scale(d3.scale.linear(), d3_time_scaleUTCMethods, d3_time_scaleUTCFormat);
+};
+})();