Skip to content

Commit

Permalink
adopt d3-time’s ticks
Browse files Browse the repository at this point in the history
  • Loading branch information
mbostock committed Apr 10, 2021
1 parent 8afe6bd commit 80ff9b2
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 78 deletions.
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -37,7 +37,7 @@
"d3-array": "^2.3.0",
"d3-format": "1 - 2",
"d3-interpolate": "1.2.0 - 2",
"d3-time": "1 - 2",
"d3-time": "^2.1.1",
"d3-time-format": "2 - 3"
},
"devDependencies": {
Expand Down
81 changes: 8 additions & 73 deletions src/time.js
@@ -1,18 +1,9 @@
import {bisector, tickStep} from "d3-array";
import {timeYear, timeMonth, timeWeek, timeDay, timeHour, timeMinute, timeSecond, timeMillisecond} from "d3-time";
import {timeYear, timeMonth, timeWeek, timeDay, timeHour, timeMinute, timeSecond, timeTicks, timeTickInterval} from "d3-time";
import {timeFormat} from "d3-time-format";
import continuous, {copy} from "./continuous.js";
import {initRange} from "./init.js";
import nice from "./nice.js";

var durationSecond = 1000,
durationMinute = durationSecond * 60,
durationHour = durationMinute * 60,
durationDay = durationHour * 24,
durationWeek = durationDay * 7,
durationMonth = durationDay * 30,
durationYear = durationDay * 365;

function date(t) {
return new Date(t);
}
Expand All @@ -21,7 +12,7 @@ function number(t) {
return t instanceof Date ? +t : +new Date(+t);
}

export function calendar(year, month, week, day, hour, minute, second, millisecond, format) {
export function calendar(ticks, tickInterval, year, month, week, day, hour, minute, second, format) {
var scale = continuous(),
invert = scale.invert,
domain = scale.domain;
Expand All @@ -35,27 +26,6 @@ export function calendar(year, month, week, day, hour, minute, second, milliseco
formatMonth = format("%B"),
formatYear = format("%Y");

var tickIntervals = [
[second, 1, durationSecond],
[second, 5, 5 * durationSecond],
[second, 15, 15 * durationSecond],
[second, 30, 30 * durationSecond],
[minute, 1, durationMinute],
[minute, 5, 5 * durationMinute],
[minute, 15, 15 * durationMinute],
[minute, 30, 30 * durationMinute],
[ hour, 1, durationHour ],
[ hour, 3, 3 * durationHour ],
[ hour, 6, 6 * durationHour ],
[ hour, 12, 12 * durationHour ],
[ day, 1, durationDay ],
[ day, 2, 2 * durationDay ],
[ week, 1, durationWeek ],
[ month, 1, durationMonth ],
[ month, 3, 3 * durationMonth ],
[ year, 1, durationYear ]
];

function tickFormat(date) {
return (second(date) < date ? formatMillisecond
: minute(date) < date ? formatSecond
Expand All @@ -66,33 +36,6 @@ export function calendar(year, month, week, day, hour, minute, second, milliseco
: formatYear)(date);
}

function tickInterval(interval, start, stop) {
if (interval == null) interval = 10;

// If a desired tick count is specified, pick a reasonable tick interval
// based on the extent of the domain and a rough estimate of tick size.
// Otherwise, assume interval is already a time interval and use it.
if (typeof interval === "number") {
var target = Math.abs(stop - start) / interval,
i = bisector(function(i) { return i[2]; }).right(tickIntervals, target),
step;
if (i === tickIntervals.length) {
step = tickStep(start / durationYear, stop / durationYear, interval);
interval = year;
} else if (i) {
i = tickIntervals[target / tickIntervals[i - 1][2] < tickIntervals[i][2] / target ? i - 1 : i];
step = i[1];
interval = i[0];
} else {
step = Math.max(tickStep(start, stop, interval), 1);
interval = millisecond;
}
return interval.every(step);
}

return interval;
}

scale.invert = function(y) {
return new Date(invert(y));
};
Expand All @@ -102,15 +45,8 @@ export function calendar(year, month, week, day, hour, minute, second, milliseco
};

scale.ticks = function(interval) {
var d = domain(),
t0 = d[0],
t1 = d[d.length - 1],
r = t1 < t0,
t;
if (r) t = t0, t0 = t1, t1 = t;
t = tickInterval(interval, t0, t1);
t = t ? t.range(t0, t1 + 1) : []; // inclusive stop
return r ? t.reverse() : t;
var d = domain();
return ticks(d[0], d[d.length - 1], interval == null ? 10 : interval);
};

scale.tickFormat = function(count, specifier) {
Expand All @@ -119,18 +55,17 @@ export function calendar(year, month, week, day, hour, minute, second, milliseco

scale.nice = function(interval) {
var d = domain();
return (interval = tickInterval(interval, d[0], d[d.length - 1]))
? domain(nice(d, interval))
: scale;
if (!interval || typeof interval.range !== "function") interval = tickInterval(d[0], d[d.length - 1], interval == null ? 10 : interval);
return interval ? domain(nice(d, interval)) : scale;
};

scale.copy = function() {
return copy(scale, calendar(year, month, week, day, hour, minute, second, millisecond, format));
return copy(scale, calendar(ticks, tickInterval, year, month, week, day, hour, minute, second, format));
};

return scale;
}

export default function time() {
return initRange.apply(calendar(timeYear, timeMonth, timeWeek, timeDay, timeHour, timeMinute, timeSecond, timeMillisecond, timeFormat).domain([new Date(2000, 0, 1), new Date(2000, 0, 2)]), arguments);
return initRange.apply(calendar(timeTicks, timeTickInterval, timeYear, timeMonth, timeWeek, timeDay, timeHour, timeMinute, timeSecond, timeFormat).domain([new Date(2000, 0, 1), new Date(2000, 0, 2)]), arguments);
}
6 changes: 3 additions & 3 deletions src/utcTime.js
@@ -1,8 +1,8 @@
import {calendar} from "./time.js";
import {utcYear, utcMonth, utcWeek, utcDay, utcHour, utcMinute, utcSecond, utcTicks, utcTickInterval} from "d3-time";
import {utcFormat} from "d3-time-format";
import {utcYear, utcMonth, utcWeek, utcDay, utcHour, utcMinute, utcSecond, utcMillisecond} from "d3-time";
import {calendar} from "./time.js";
import {initRange} from "./init.js";

export default function utcTime() {
return initRange.apply(calendar(utcYear, utcMonth, utcWeek, utcDay, utcHour, utcMinute, utcSecond, utcMillisecond, utcFormat).domain([Date.UTC(2000, 0, 1), Date.UTC(2000, 0, 2)]), arguments);
return initRange.apply(calendar(utcTicks, utcTickInterval, utcYear, utcMonth, utcWeek, utcDay, utcHour, utcMinute, utcSecond, utcFormat).domain([Date.UTC(2000, 0, 1), Date.UTC(2000, 0, 2)]), arguments);
}
9 changes: 8 additions & 1 deletion yarn.lock
Expand Up @@ -207,7 +207,7 @@ cross-spawn@^7.0.2:
shebang-command "^2.0.0"
which "^2.0.1"

d3-array@^2.3.0:
d3-array@2, d3-array@^2.3.0:
version "2.12.1"
resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-2.12.1.tgz#e20b41aafcdffdf5d50928004ececf815a465e81"
integrity sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==
Expand Down Expand Up @@ -243,6 +243,13 @@ d3-array@^2.3.0:
resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-2.0.0.tgz#ad7c127d17c67bd57a4c61f3eaecb81108b1e0ab"
integrity sha512-2mvhstTFcMvwStWd9Tj3e6CEqtOivtD8AUiHT8ido/xmzrI9ijrUUihZ6nHuf/vsScRBonagOdj0Vv+SEL5G3Q==

d3-time@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-2.1.1.tgz#e9d8a8a88691f4548e68ca085e5ff956724a6682"
integrity sha512-/eIQe/eR4kCQwq7yxi7z4c6qEXf2IYGcjoWB5OOQy4Tq9Uv39/947qlDcN2TLkiTzQWzvnsuYPB9TrWaNfipKQ==
dependencies:
d3-array "2"

debug@^4.0.1, debug@^4.1.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee"
Expand Down

3 comments on commit 80ff9b2

@Pringels
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might be mistaken but this definitely seems like a breaking change even though the version bump was minor: 3.2 -> 3.3
Any libraries making use of d3-scale will break if they declare the dependency using ^@3.2.4

Is this a correct assumption? Would you be willing to revert this and re-release it as part of a major version? Or at least provide some backward compatibility?

@curran
Copy link
Contributor

@curran curran commented on 80ff9b2 May 11, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Pringels In what way would they break?

@Pringels
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@curran because d3-scale is now incompatible with versions of d3-time lower than 2.1.x

Please sign in to comment.