Skip to content

Commit aea6330

Browse files
authored
Merge pull request #5180 from plotly/adjust-tick0-for-a-weekly-dtick
Adjust tick0 for weekly time periods
2 parents b521323 + 75a2029 commit aea6330

File tree

5 files changed

+74
-17
lines changed

5 files changed

+74
-17
lines changed

src/lib/dates.js

+16-2
Original file line numberDiff line numberDiff line change
@@ -45,17 +45,31 @@ function isWorldCalendar(calendar) {
4545
/*
4646
* dateTick0: get the canonical tick for this calendar
4747
*
48+
* integer weekdays : Saturday: 0, Sunday: 1, Monday: 2, etc.
49+
*/
50+
exports.dateTick0 = function(calendar, dayOfWeek) {
51+
var tick0 = _dateTick0(calendar, !!dayOfWeek);
52+
if(dayOfWeek < 2) return tick0;
53+
54+
var v = exports.dateTime2ms(tick0, calendar);
55+
v += ONEDAY * (dayOfWeek - 1); // shift Sunday to Monday, etc.
56+
return exports.ms2DateTime(v, 0, calendar);
57+
};
58+
59+
/*
60+
* _dateTick0: get the canonical tick for this calendar
61+
*
4862
* bool sunday is for week ticks, shift it to a Sunday.
4963
*/
50-
exports.dateTick0 = function(calendar, sunday) {
64+
function _dateTick0(calendar, sunday) {
5165
if(isWorldCalendar(calendar)) {
5266
return sunday ?
5367
Registry.getComponentMethod('calendars', 'CANONICAL_SUNDAY')[calendar] :
5468
Registry.getComponentMethod('calendars', 'CANONICAL_TICK')[calendar];
5569
} else {
5670
return sunday ? '2000-01-02' : '2000-01-01';
5771
}
58-
};
72+
}
5973

6074
/*
6175
* dfltRange: for each calendar, give a valid default range

src/plots/cartesian/axes.js

+8-9
Original file line numberDiff line numberDiff line change
@@ -630,12 +630,14 @@ axes.calcTicks = function calcTicks(ax, opts) {
630630
generateTicks();
631631

632632
var isPeriod = ax.ticklabelmode === 'period';
633-
if(isPeriod) {
633+
var addedPreTick0Label = false;
634+
if(isPeriod && tickVals[0]) {
634635
// add one label to show pre tick0 period
635636
tickVals.unshift({
636637
minor: false,
637638
value: axes.tickIncrement(tickVals[0].value, ax.dtick, !axrev, ax.caldendar)
638639
});
640+
addedPreTick0Label = true;
639641
}
640642

641643
if(ax.rangebreaks) {
@@ -778,7 +780,7 @@ axes.calcTicks = function calcTicks(ax, opts) {
778780
ticksOut.push(t);
779781
}
780782

781-
if(isPeriod) {
783+
if(isPeriod && addedPreTick0Label) {
782784
var removedPreTick0Label = false;
783785

784786
for(i = 0; i < ticksOut.length; i++) {
@@ -965,7 +967,7 @@ axes.autoTicks = function(ax, roughDTick) {
965967
}
966968

967969
if(ax.type === 'date') {
968-
ax.tick0 = Lib.dateTick0(ax.calendar);
970+
ax.tick0 = Lib.dateTick0(ax.calendar, 0);
969971
// the criteria below are all based on the rough spacing we calculate
970972
// being > half of the final unit - so precalculate twice the rough val
971973
var roughX2 = 2 * roughDTick;
@@ -982,14 +984,11 @@ axes.autoTicks = function(ax, roughDTick) {
982984
// get week ticks on sunday
983985
// this will also move the base tick off 2000-01-01 if dtick is
984986
// 2 or 3 days... but that's a weird enough case that we'll ignore it.
985-
ax.tick0 = Lib.dateTick0(ax.calendar, true);
986-
987987
var tickformat = axes.getTickFormat(ax);
988988
if(/%[uVW]/.test(tickformat)) {
989-
// replace Sunday with Monday for ISO and Monday-based formats
990-
var len = ax.tick0.length;
991-
var lastD = +ax.tick0[len - 1];
992-
ax.tick0 = ax.tick0.substring(0, len - 2) + String(lastD + 1);
989+
ax.tick0 = Lib.dateTick0(ax.calendar, 2); // Monday
990+
} else {
991+
ax.tick0 = Lib.dateTick0(ax.calendar, 1); // Sunday
993992
}
994993
} else if(roughX2 > ONEHOUR) {
995994
ax.dtick = roundDTick(roughDTick, ONEHOUR, roundBase24);

src/plots/cartesian/clean_ticks.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010

1111
var isNumeric = require('fast-isnumeric');
1212
var Lib = require('../../lib');
13-
var ONEDAY = require('../../constants/numerical').ONEDAY;
13+
var constants = require('../../constants/numerical');
14+
var ONEDAY = constants.ONEDAY;
15+
var ONEWEEK = constants.ONEWEEK;
1416

1517
/**
1618
* Return a validated dtick value for this axis
@@ -75,7 +77,9 @@ exports.dtick = function(dtick, axType) {
7577
*/
7678
exports.tick0 = function(tick0, axType, calendar, dtick) {
7779
if(axType === 'date') {
78-
return Lib.cleanDate(tick0, Lib.dateTick0(calendar));
80+
return Lib.cleanDate(tick0,
81+
Lib.dateTick0(calendar, (dtick % ONEWEEK === 0) ? 1 : 0)
82+
);
7983
}
8084
if(dtick === 'D1' || dtick === 'D2') {
8185
// D1 and D2 modes ignore tick0 entirely

src/traces/scatter/period_defaults.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ var numConstants = require('../../constants/numerical');
1313
var ONEWEEK = numConstants.ONEWEEK;
1414

1515
function getPeriod0Dflt(period, calendar) {
16-
var n = period / ONEWEEK;
17-
return dateTick0(calendar, Math.round(n) === n);
16+
if(period % ONEWEEK === 0) {
17+
return dateTick0(calendar, 1); // Sunday
18+
}
19+
return dateTick0(calendar, 0);
1820
}
1921

2022
module.exports = function handlePeriodDefaults(traceIn, traceOut, layout, coerce, opts) {

test/jasmine/tests/axes_test.js

+40-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ var Cartesian = require('@src/plots/cartesian');
1313
var Axes = require('@src/plots/cartesian/axes');
1414
var Fx = require('@src/components/fx');
1515
var supplyLayoutDefaults = require('@src/plots/cartesian/layout_defaults');
16-
var BADNUM = require('@src/constants/numerical').BADNUM;
17-
var ONEDAY = require('@src/constants/numerical').ONEDAY;
16+
var numerical = require('@src/constants/numerical');
17+
var BADNUM = numerical.BADNUM;
18+
var ONEDAY = numerical.ONEDAY;
19+
var ONEWEEK = numerical.ONEWEEK;
1820

1921
var createGraphDiv = require('../assets/create_graph_div');
2022
var destroyGraphDiv = require('../assets/destroy_graph_div');
@@ -6020,6 +6022,42 @@ describe('Test axes', function() {
60206022
.then(done);
60216023
});
60226024
});
6025+
6026+
[undefined, '%U', '%V', '%W'].forEach(function(tickformat) {
6027+
it('with ' + tickformat + ' tickformat, should default tick0 on a Sunday when dtick is a round number of weeks', function(done) {
6028+
var fig = {
6029+
data: [
6030+
{
6031+
showlegend: false,
6032+
type: 'bar',
6033+
width: ONEWEEK,
6034+
xperiod: ONEWEEK,
6035+
x: [
6036+
'2020-09-16',
6037+
'2020-09-24',
6038+
'2020-09-30'
6039+
],
6040+
y: [3, 2, 4]
6041+
}
6042+
],
6043+
layout: {
6044+
xaxis: {
6045+
tickformat: tickformat,
6046+
dtick: ONEWEEK,
6047+
ticklabelmode: 'period',
6048+
showgrid: true,
6049+
}
6050+
}
6051+
};
6052+
6053+
Plotly.newPlot(gd, fig)
6054+
.then(function() {
6055+
expect(gd._fullLayout.xaxis.tick0).toBe('2000-01-02');
6056+
})
6057+
.catch(failTest)
6058+
.then(done);
6059+
});
6060+
});
60236061
});
60246062
});
60256063

0 commit comments

Comments
 (0)