Skip to content
Merged
5 changes: 4 additions & 1 deletion lib/locales/fr.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ module.exports = {
],
date: '%d/%m/%Y',
decimal: ',',
thousands: ' '
thousands: ' ',
year: '%Y',
month: '%b %Y',
dayMonth: '%e %b'
}
};
54 changes: 7 additions & 47 deletions src/lib/dates.js
Original file line number Diff line number Diff line change
Expand Up @@ -433,18 +433,6 @@ function formatTime(x, tr) {
return timeStr;
}

// TODO: do these strings need to be localized?
// ie this gives "Dec 13, 2017" but some languages may want eg "13-Dec 2017"
var yearFormatD3 = '%Y';
var monthFormatD3 = '%b %Y';
var dayFormatD3 = '%b %-d';
var yearMonthDayFormatD3 = '%b %-d, %Y';

function yearFormatWorld(cDate) { return cDate.formatDate('yyyy'); }
function monthFormatWorld(cDate) { return cDate.formatDate('M yyyy'); }
function dayFormatWorld(cDate) { return cDate.formatDate('M d'); }
function yearMonthDayFormatWorld(cDate) { return cDate.formatDate('M d, yyyy'); }

/*
* formatDate: turn a date into tick or hover label text.
*
Expand All @@ -462,49 +450,21 @@ function yearMonthDayFormatWorld(cDate) { return cDate.formatDate('M d, yyyy');
* the axis may choose to strip things after it when they don't change from
* one tick to the next (as it does with automatic formatting)
*/
exports.formatDate = function(x, fmt, tr, formatter, calendar) {
var headStr,
dateStr;

exports.formatDate = function(x, fmt, tr, formatter, calendar, extraFormat) {
calendar = isWorldCalendar(calendar) && calendar;

if(fmt) return modDateFormat(fmt, x, formatter, calendar);

if(calendar) {
try {
var dateJD = Math.floor((x + 0.05) / ONEDAY) + EPOCHJD,
cDate = Registry.getComponentMethod('calendars', 'getCal')(calendar)
.fromJD(dateJD);

if(tr === 'y') dateStr = yearFormatWorld(cDate);
else if(tr === 'm') dateStr = monthFormatWorld(cDate);
else if(tr === 'd') {
headStr = yearFormatWorld(cDate);
dateStr = dayFormatWorld(cDate);
}
else {
headStr = yearMonthDayFormatWorld(cDate);
dateStr = formatTime(x, tr);
}
}
catch(e) { return 'Invalid'; }
}
else {
var d = new Date(Math.floor(x + 0.05));

if(tr === 'y') dateStr = formatter(yearFormatD3)(d);
else if(tr === 'm') dateStr = formatter(monthFormatD3)(d);
if(!fmt) {
if(tr === 'y') fmt = extraFormat.year;
else if(tr === 'm') fmt = extraFormat.month;
else if(tr === 'd') {
headStr = formatter(yearFormatD3)(d);
dateStr = formatter(dayFormatD3)(d);
fmt = extraFormat.dayMonth + '\n' + extraFormat.year;
}
else {
headStr = formatter(yearMonthDayFormatD3)(d);
dateStr = formatTime(x, tr);
return formatTime(x, tr) + '\n' + modDateFormat(extraFormat.dayMonthYear, x, formatter, calendar);
}
}

return dateStr + (headStr ? '\n' + headStr : '');
return modDateFormat(fmt, x, formatter, calendar);
};

/*
Expand Down
18 changes: 11 additions & 7 deletions src/locale-en.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/**
* Copyright 2012-2018, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
* Copyright 2012-2018, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

Expand Down Expand Up @@ -32,6 +32,10 @@ module.exports = {
decimal: '.',
thousands: ',',
grouping: [3],
currency: ['$', '']
currency: ['$', ''],
year: '%Y',
month: '%b %Y',
dayMonth: '%b %e',
dayMonthYear: '%b %e, %Y'
Copy link
Collaborator

Choose a reason for hiding this comment

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

%e is padded with a space for 1-digit days - we should switch back to %-d, which has no padding (in fr.js as well). That's responsible for the image test failures.

}
};
2 changes: 1 addition & 1 deletion src/plots/cartesian/axes.js
Original file line number Diff line number Diff line change
Expand Up @@ -1292,7 +1292,7 @@ function formatDate(ax, out, hover, extraPrecision) {
else tr = {y: 'm', m: 'd', d: 'M', M: 'S', S: 4}[tr];
}

var dateStr = Lib.formatDate(out.x, fmt, tr, ax._dateFormat, ax.calendar),
var dateStr = Lib.formatDate(out.x, fmt, tr, ax._dateFormat, ax.calendar, ax._extraFormat),
headStr;

var splitIndex = dateStr.indexOf('\n');
Expand Down
1 change: 1 addition & 0 deletions src/plots/cartesian/set_convert.js
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,7 @@ module.exports = function setConvert(ax, fullLayout) {
var locale = fullLayout._d3locale;
if(ax.type === 'date') {
ax._dateFormat = locale ? locale.timeFormat.utc : d3.time.format.utc;
ax._extraFormat = fullLayout._extraFormat;
}
// occasionally we need _numFormat to pass through
// even though it won't be needed by this axis
Expand Down
16 changes: 12 additions & 4 deletions src/plots/plots.js
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ plots.supplyDefaults = function(gd) {
};
newFullLayout._traceWord = _(gd, 'trace');

var formatObj = getD3FormatObj(gd);
var formatObj = getFormatObj(gd, d3FormatKeys);

// first fill in what we can of layout without looking at data
// because fullData needs a few things from layout
Expand Down Expand Up @@ -342,6 +342,7 @@ plots.supplyDefaults = function(gd) {
}

newFullLayout._d3locale = getFormatter(formatObj, newFullLayout.separators);
newFullLayout._extraFormat = getFormatObj(gd, extraFormatKeys);

newFullLayout._initialAutoSizeIsDone = true;

Expand Down Expand Up @@ -481,21 +482,28 @@ function remapTransformedArrays(cd0, newTrace) {
}
}

var formatKeys = [
var d3FormatKeys = [
'days', 'shortDays', 'months', 'shortMonths', 'periods',
'dateTime', 'date', 'time',
'decimal', 'thousands', 'grouping', 'currency'
];

var extraFormatKeys = [
'year', 'month', 'dayMonth', 'dayMonthYear'
];

/**
* getD3FormatObj: use _context to get the d3.locale argument object.
* getFormatObj: use _context to get the format object from locale.
* Used to get d3.locale argument object and extraFormat argument object
*
* Regarding d3.locale argument :
* decimal and thousands can be overridden later by layout.separators
* grouping and currency are not presently used by our automatic number
* formatting system but can be used by custom formats.
*
* @returns {object} d3.locale format object
*/
function getD3FormatObj(gd) {
function getFormatObj(gd, formatKeys) {
var locale = gd._context.locale;
if(!locale) locale === 'en-US';

Expand Down