如何让 D3 数据驱动文档在正确的时区显示 moment.js 日期时间?
How do I get D3 Data Driven Document to display a moment.js datetime in the correct time zone?
我正在开发一个 AngularJS 单页应用程序,它使用 D3
图表来显示在世界各地不同时区记录的数据。图表上的时间轴需要显示其原始时区的时间。
要绘制的数据是一组值、时间戳对。时间戳包含自己的时区信息,并以 ISO format
编码(例如 "2003-12-14T12:00:00.000+08:00"
)。所以 json 看起来像这样:
"values": [
["2003-12-14T12:00:00.000+08:00", 10],
["2003-12-14T13:00:00.000+08:00", 20],
["2003-12-14T14:00:00.000+08:00", 30],
["2003-12-14T15:00:00.000+08:00", 40],
["2003-12-14T16:00:00.000+08:00", 50]
]
然后将时间戳和值添加到对象中,其中时间戳转换为时刻:
data = values[1];
timeStamp = moment.parseZone(values[0]);
然后将这些样本传递给 D3
进行显示。但是,当它们传递给 D3
时,时间刻度显示为本地浏览器时间。这不好 - 我不知道如何让它在正确的时区显示数据。
我尝试使用自定义方法设置 xAxis.tickFormat
,但传递给它的时间是标准 Javascript 日期对象,在当地时区。
此外,时区可能会在图表中间发生变化(由于夏令时),因此不能简单地保持时区偏移值并进行手动调整。
答案是编写一个方法来计算和 returns 刻度值,以及类似的刻度格式,如来自@LarsKotthoff 的 this link 给出的那样。
最终代码需要是这样的:
xAxis = d3.svg.axis()
.scale(xScale)
.tickValues(calculateTickValue)
.tickFormat(getTickFormat);
var getTickFormat = function(date){
var diff = date.format("DD") != previousDate.format("DD");
if (diff){
previousDate = date;
return date.format("MMM Do, HH:mm");
}
return date.format(tickFormat);
}
var calculateTickValue = function(){
var startTime = scope.segment.startTime;
var endTime = scope.segment.endTime;
var tickValues = [];
var difference = moment.duration(endTime.diff(startTime));
var maximumTicks = calculateMaximumTicks();
if (difference.asHours() >= maximumTicks){
tickValues = calculateHoursTicks(startTime, endTime, maximumTicks);
tickFormat = "HH:mm";
}
else {
tickValues = caclulateMinutesTicks(startTime, endTime, maximumTicks);
tickFormat = "HH:mm";
}
previousDate = startTime;
return tickValues;
}
显然,根据您需要的比例,可以自定义年、月、日、小时等。
我正在开发一个 AngularJS 单页应用程序,它使用 D3
图表来显示在世界各地不同时区记录的数据。图表上的时间轴需要显示其原始时区的时间。
要绘制的数据是一组值、时间戳对。时间戳包含自己的时区信息,并以 ISO format
编码(例如 "2003-12-14T12:00:00.000+08:00"
)。所以 json 看起来像这样:
"values": [
["2003-12-14T12:00:00.000+08:00", 10],
["2003-12-14T13:00:00.000+08:00", 20],
["2003-12-14T14:00:00.000+08:00", 30],
["2003-12-14T15:00:00.000+08:00", 40],
["2003-12-14T16:00:00.000+08:00", 50]
]
然后将时间戳和值添加到对象中,其中时间戳转换为时刻:
data = values[1];
timeStamp = moment.parseZone(values[0]);
然后将这些样本传递给 D3
进行显示。但是,当它们传递给 D3
时,时间刻度显示为本地浏览器时间。这不好 - 我不知道如何让它在正确的时区显示数据。
我尝试使用自定义方法设置 xAxis.tickFormat
,但传递给它的时间是标准 Javascript 日期对象,在当地时区。
此外,时区可能会在图表中间发生变化(由于夏令时),因此不能简单地保持时区偏移值并进行手动调整。
答案是编写一个方法来计算和 returns 刻度值,以及类似的刻度格式,如来自@LarsKotthoff 的 this link 给出的那样。
最终代码需要是这样的:
xAxis = d3.svg.axis()
.scale(xScale)
.tickValues(calculateTickValue)
.tickFormat(getTickFormat);
var getTickFormat = function(date){
var diff = date.format("DD") != previousDate.format("DD");
if (diff){
previousDate = date;
return date.format("MMM Do, HH:mm");
}
return date.format(tickFormat);
}
var calculateTickValue = function(){
var startTime = scope.segment.startTime;
var endTime = scope.segment.endTime;
var tickValues = [];
var difference = moment.duration(endTime.diff(startTime));
var maximumTicks = calculateMaximumTicks();
if (difference.asHours() >= maximumTicks){
tickValues = calculateHoursTicks(startTime, endTime, maximumTicks);
tickFormat = "HH:mm";
}
else {
tickValues = caclulateMinutesTicks(startTime, endTime, maximumTicks);
tickFormat = "HH:mm";
}
previousDate = startTime;
return tickValues;
}
显然,根据您需要的比例,可以自定义年、月、日、小时等。