Unlisted
Edited
Jun 25, 2023
1 star
Insert cell
Insert cell
Plot = FileAttachment("plot.umd.js").url().then(require)
Insert cell
Insert cell
Plot.plot({
x: {
type: "utc",
domain: [0, 10 ** u],
line: true
}
})
Insert cell
formats = {
const durationSecond = 1000;
const durationMinute = durationSecond * 60;
const durationHour = durationMinute * 60;
const durationDay = durationHour * 24;
const durationWeek = durationDay * 7;
const durationMonth = durationDay * 30;
const durationYear = durationDay * 365;

return [
["millisecond", 0.5 * durationSecond],
["second", durationSecond],
["second", 30 * durationSecond],
["minute", durationMinute],
["minute", 30 * durationMinute],
["hour", durationHour],
["hour", 12 * durationHour],
["day", durationDay],
["day", 2 * durationDay],
["week", durationWeek],
["month", durationMonth],
["month", 3 * durationMonth],
["year", durationYear]
];
}
Insert cell
transitions = d3
.pairs(formats)
.map(([[fa, da], [fb, db]]) => [fa, fb, Math.sqrt(da * db)])
.filter(([fa, fb]) => fa !== fb)
Insert cell
Plot.plot({
x: {
label: "time extent",
insetLeft: 5,
grid: true,
type: "log",
ticks: [
1,
1000,
60 * 1000,
60 * 60 * 1000,
24 * 60 * 60 * 1000,
24 * 60 * 60 * 1000 * 7,
24 * 60 * 60 * 1000 * 28,
24 * 60 * 60 * 1000 * 31,
24 * 60 * 60 * 1000 * 364.25
],
tickFormat: (d, i) =>
["1ms", "1”", "1’", "1h", "1day", "1week", "1mo", "", "1year"][i]
},
y: { domain: formats.map((d) => d[0]), reverse: true, label: "format" },
marginLeft: 100,
marks: [
Plot.lineY(d3.range(-1, 26, 0.01), {
y: (d) =>
formats[
d3.bisector(([, step]) => Math.log(step)).center(formats, d)
][0],
x: (d) => Math.exp(d)
}),
Plot.text(transitions, {
x: "2",
y: "1",
text: (d) => tFormat(d["2"]),
dy: -6,
textAnchor: "end"
})
]
})
Insert cell
// hacky half-way duration formatter
function tFormat(duration) {
return duration < 1000
? `${duration.toFixed(0)}ms`
: duration < 60 * 1000
? `${(duration / 1000).toFixed(1)}s`
: duration < 60 * 60 * 1000
? `${(duration / 60000).toFixed(1)}m`
: duration < 24 * 60 * 60 * 1000
? `${Math.floor(duration / 3600000)}h${Math.round(
60 * (duration / 3600000 - Math.floor(duration / 3600000))
)}`
: duration < 7 * 24 * 60 * 60 * 1000
? `${Math.floor(duration / (24 * 3600000))}d${tFormat(
24 *
3600000 *
(duration / (24 * 3600000) - Math.floor(duration / (24 * 3600000)))
)}`
: `${(duration / (24 * 3600000)).toPrecision(3)}d`;
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more