d3js time format with specific timezone - d3.js

I am trying to parse date with my specific timezone - not utc or browser. I am using
d3.timeFormat("%H:%M %p");
but this function is unsing browser timezone automatically.
d3.utcFormat("%H:%M %p"); // is using utc
I am thinking about using moment.js but don't know how. Any idea?
------UPDATE---------------------------------------
I am using unix timestamps as number to do linear scaling.
var xScale = d3.scaleLinear()
.range([0, width])
.domain([minTime, maxTime]);
and just parsing it when display it
var xAxis = d3.axisBottom()
.scale(xScale)
.ticks(7)
.tickFormat(d3.timeFormat("%H:%M %p"));
so input is e.g. 1647245248 and I want to set timezones that I get from moment.js list.
So I need to add timezone in data in unix timestamp or just in d3 display axis.

Related

Use dates as numbers, but format them as dates in UI

Let's take this example.
https://d3fc.io/examples/series-canvas-candlestick/
It defines X scale as a time scale.
const xScale = d3
.scaleTime()
.domain(fc.extentDate().accessors([d => d.date])(data));
To prevent multiple tick to date conversion in my zoom handler, I'd like to always work with number, but keep UI showing these numbers as dates. So, I change the code above to linear scale.
const xScale = d3
.scaleLinear()
.domain(fc.extentLinear().accessors([d => d.date.getTime()])(data));
Everything works fine, but now I have an X scale showing numbers instead of dates. The question is, how to add mapper or formatter that would show these numbers as dates in UI? I see some examples of d3.tickFormat, but not sure how to apply it in d3fc.
https://observablehq.com/#d3/axis-ticks
You supply your scales to the D3FC cartesian chart, which then couples these with the axes that it creates for you.
As mentioned in the documentation the chart exposes the properties of the X and Y axes with an x and y prefix. So, if you want to change the tick format for the X axis, which you would typically do via the tickFormat property, you instead do the following:
var chart = fc.chartCartesian(
d3.scaleLinear(),
d3.scaleLinear()
)
.xTickFormat(/* ... formatter goes here */);

D3js first tick label is missing

I don't understand why the first label (2000) is missing. I compared it to many examples without finding why.
let xAxisScale = d3
.scaleTime()
.domain([min, max]) // 2000, 2013
.range([0, width]);
xAxis = d3
.axisBottom()
.tickFormat(d3.timeFormat('%Y'))
.tickPadding(5)
.ticks(d3.timeYear)
.scale(xAxisScale);
gx = innerSpace
.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + height + ')')
.call(xAxis);
Do you see any errors ?
Thanks !
This problem may be due to small variations in min date. It depends on the way you construct min date.
For example, new Date('2000-01-01') does not include year 2000 if your time zone is >0. You can write new Date('2000-01-01T00:00:00Z') to use UTC.
Also, if you use new Date(YYYY, MM, DD), you should take into account, that month starts from zero, while day starts from one.
Read about correct way of dealing with that problem here: http://bl.ocks.org/jebeck/9671241
Next to your nice answer I tried different ways to get a datetime without utc / gmt problems but didn't find a nice solution of dealing with it for all web explorer without using library.
The best solution I find is to use the library momentjs because momentjs will nicely handle the timezone :
const minMoment = moment(`01/01/${minDate}`, 'DD/MM/YYYY', true);
const maxMoment = moment(`01/01/${maxDate}`, 'DD/MM/YYYY', true);
this.xAxisScale = d3
.scaleTime()
.domain([minMoment.toDate(), maxMoment.toDate()])
.range([0, width]);

d3 time axis NaN error

I'm attempting to make a simple line chart in d3 v5 and I'm having trouble with the x axis.
Here's a sample of my data
{
"2015-05-02":"1",
"2015-05-03":"2",
"2015-05-04":"1",
"2015-05-13":"3",
"2015-05-15":"2",
"2015-05-16":"2",
"2015-05-20":"1",
"2015-05-26":"11",
"2015-05-27":"1",
"2015-05-28":"7",
"2015-05-29":"260",
}
Here I try to parse my keys as date objects
//attempting to parse dates
//the dates are strings (eg. 2015-02-18)
dates = d3.keys(data);
$.each(dates, function(thisDate){
var formatDate = d3.timeParse("%Y-%m-%d");
dates[thisDate] = formatDate(dates[thisDate]);
});
After looping through my dates, they are date objects that look like this:
Wed Feb 18 2015 00:00:00 GMT-0600 (Central Standard Time)
Then I set my mins and maxs:
minDate = d3.min(dates); //Wed Feb 18 2015 00:00:00 GMT-0600 (Central Standard Time)
maxDate = d3.max(dates); //Sat Dec 09 2017 00:00:00 GMT-0600 (Central Standard Time)
And set my scale like this:
//x scale
var xScale = d3.scaleTime()
.domain([minDate,maxDate])
.range(0,width);
Then I tried to display my axis like this
//x axis
var xAxis = d3.axisBottom(xScale);
svg.append('g')
.call(xAxis);
It's currently giving me this error when I try to call the x axis:
Error: <path> attribute d: Expected number, "MNaN,6V0.5HNaNV6".
My path wants numbers? But I just made them javascript date objects. I used to dabble in d3 v3, but I'm pretty rusty. Any links to good v5 examples would also be much appreciated.
Thanks!
I forgot the square brackets on my range...
//x scale
var xScale = d3.scaleTime()
.domain([minDate,maxDate])
.range(0,width);
Should have been
//x scale
var xScale = d3.scaleTime()
.domain([minDate,maxDate])
.range([0,width]);
Shout out to this post for the answer: D3.js error using timescale (path is NaN)
Now on to the next problem...
why don't you parse the dates like this
var formatDate = d3.timeParse("%Y-%m-%d");
var dates = d3.keys(data).map( d => formatDate(d) );
var xScale = d3.scaleTime()
.domain(d3.extent(dates))
.range([0,width]);
var data = {
"2015-05-02":"1",
"2015-05-03":"2",
"2015-05-04":"1",
"2015-05-13":"3",
"2015-05-15":"2",
"2015-05-16":"2",
"2015-05-20":"1",
"2015-05-26":"11",
"2015-05-27":"1",
"2015-05-28":"7",
"2015-05-29":"260"
};
var width = 500;
var formatDate = d3.timeParse("%Y-%m-%d");
var dates = d3.keys(data).map( d => formatDate(d) );
var xScale = d3.scaleTime()
.domain(d3.extent(dates))
.range([0,width]);
console.log('xScale-domain', xScale.domain());
<script src="http://d3js.org/d3.v5.min.js" charset="utf-8"></script>

D3 x-axis date not showing for Sundays

I'm using the code below to display the day of the week and the month value for my data. D3 displays the date as expected e.g. "Sat 18" but for Sunday it shows the month instead e.g. "Oct 19"!
Can't figure out why this is happening. The code is:
var xScale = d3.time.scale()
.domain([new Date($scope.dataset[0][0].time),d3.time.day.offset(new Date($scope.dataset[0][$scope.dataset[0].length-2].time),2)])
.rangeRound([0, w-0]);
var xAxis = d3.svg.axis()
.scale(xScale)
.orient('bottom')
.ticks(d3.time.days,1);
Any ideas why this is happening? the sample dataset looks like this:
{time: "2014-10-19",y: 0,y0: 0}
By default, D3 will apply some adaptive formatting to the date tick values (see "This set of time intervals is somewhat arbitrary and additional values may be added in the future" section), but you can override this with a specific date format, for example:
.ticks(d3.time.days,1)
.tickFormat(d3.time.format('%a %e'));
You can find the remainder of the formatting options here.

Parse-ing Date from JSON D3.js

I'm trying to parse this date using the D3.js libary.
2013-07-07 00:06:02.480270
I have tried so many variation but it always returns null
For example :
var parseDate = d3.time.format("%Y-%m-%d %H:%M:%S.%L").parse;
var parseDate = d3.time.format("%Y-%m-%d %H:%M:%S+0000").parse;
var parseDate = d3.time.format("%Y-%m-%d %H:%M:%S").parse;
It´s endless trial and error.
Any advice ?
According to the documentation, D3 expects the milliseconds to be three digits at most. You will either have to cut off the last three digits of your string or use something else to parse it.

Resources