d3 / d3-time-format Goto Github PK
View Code? Open in Web Editor NEWParse and format times, inspired by strptime and strftime.
Home Page: https://d3js.org/d3-time-format
License: ISC License
Parse and format times, inspired by strptime and strftime.
Home Page: https://d3js.org/d3-time-format
License: ISC License
I am converting milliseconds in to weeks it works fine
d3.timeFormat('%U')(new Date(d.CreationDate * 1000)) provide me an output for a 1 year for eg.
W-01, W-02, .... W-52.
What if we have there are more than one year it again gives me a W-01 and all. How can we detect if W-01 is from this year and another W-01 is from other year?
Can we customize the time format like below
W-01-2019 or W-01-19
W-01-2020 or W-01-20
Hi, as per this discussion: https://stackoverflow.com/questions/55992937/typescript-error-when-using-d3-timeformat-in-axis-tickformat
We cannot use this with timeFormat e.g.:
axisBottom(x).tickFormat(timeFormat('...'))
Will result in the error:
No overload matches this call.
Overload 1 of 3, '(format: (domainValue: string, index: number) => string): Axis<string>', gave the following error.
Argument of type '(date: Date) => string' is not assignable to parameter of type '(domainValue: string, index: number) => string'.
Types of parameters 'date' and 'domainValue' are incompatible.
Type 'string' is not assignable to type 'Date'.
Overload 2 of 3, '(format: null): Axis<string>', gave the following error.
Argument of type '(date: Date) => string' is not assignable to parameter of type 'null'.ts(2769)
Shouldn't domainValue
be compatible with type date, given this is a very common use case?
The SO solution also does not work at least with TS 3.7.2. Any idea how to fix this? I'm new to the horrors of TS.
For locales. See d3/d3-shape#23.
Hi,
i am creating bar and scatter charts using d3js and everything works fine with chrome; but when i switch to the firefox and chrome, the x attributes for positioning of bars and symbols are always set as NaN.
the code section for creating bars:
this.dataset.forEach((ds, i) => {
this.chartProps.svg.selectAll('bar')
.data(ds)
.enter().append('rect')
.style('fill', this.color[i]) // color of bar-columns
.attr('transform', 'translate(' + [margin.left - this.chartProps.xx.bandwidth() / 2, margin.top / 2] + ')')
.attr('x', d => this.chartProps.x(new Date(d3.timeFormat('%d-%b-%y')(new Date(d.TimePoint))
+ i * this.chartProps.xx.bandwidth() / this.dataset.length)
.attr('width', this.chartProps.xx.bandwidth() / this.dataset.length)
.attr('y', d => this.chartProps.y(d.Value))
.attr('height', d => this.chartProps.y(0) - this.chartProps.y(d.Value))
.append('title')
.text(d => d.Value);
});
When i don't use the d3.timeFormat()
function, the x attributes are set correctly; but then because of the time, the bars/symbols are always shifted a little.
I am not sure, if the problem related to d3/d3-time-format or DefinitlyTyped.
Thanks for your help
GET https://unpkg.com/[email protected]/locale/en-US.json 404
GET https://unpkg.com/[email protected]/locale/fr-FR.json 404
https://unpkg.com/d3-time-format@2/locale/en-US.json redirect to GET https://unpkg.com/[email protected]/locale/en-US.json 404
GET https://unpkg.com/[email protected]/locale/en-US.json 200
Any negative unix value is failed to be correctly parsed
> var parseUnix = d3.timeParse("%Q")
> parseUnix(978325200000).toString()
"Mon Jan 01 2001 00:00:00 GMT-0500 (Eastern Standard Time)"
> parseUnix(0).toString()
"Wed Dec 31 1969 19:00:00 GMT-0500 (Eastern Standard Time)"
> parseUnix(-1)
null
Note that formatting dates prior to epoch, returns negative values
> var formatUnix = d3.timeFormat("%Q");
> formatUnix(new Date(-1))
-1
> var parseUnix = d3.timeParse("%Q")
> parseUnix(formatUnix(new Date(-1)))
null
As you may have noticed that the native JS Date constructor is able to parse negative Unix time, so not a huge problem for basic tasks, but support for parsing negative values may be needed in more complex tasks.
utcParse("%Y/%m/%d")
matches the string "10/12/68", assuming the year is 10AD.
I would expect this to not match, and only match if the year is four digits long
Per #29, if a weekday is specified and a week number is not specified, and the parsed weekday does not match the weekday implied by the date, null should be returned.
The standalone library contains these directives for the specifier string:
var parses = {
"a": parseShortWeekday,
"A": parseWeekday,
"b": parseShortMonth,
"B": parseMonth,
"c": parseLocaleDateTime,
"d": parseDayOfMonth,
"e": parseDayOfMonth,
"f": parseMicroseconds,
"H": parseHour24,
"I": parseHour24,
"j": parseDayOfYear,
"L": parseMilliseconds,
"m": parseMonthNumber,
"M": parseMinutes,
"p": parsePeriod,
"Q": parseUnixTimestamp,
"s": parseUnixTimestampSeconds,
"S": parseSeconds,
"u": parseWeekdayNumberMonday,
"U": parseWeekNumberSunday,
"V": parseWeekNumberISO,
"w": parseWeekdayNumberSunday,
"W": parseWeekNumberMonday,
"x": parseLocaleDate,
"X": parseLocaleTime,
"y": parseYear,
"Y": parseFullYear,
"Z": parseZone,
"%": parseLiteralPercent
};
However, the default bundle (version 4.11.0 at the time of writing) contains only these:
var parses = {
"a": parseShortWeekday,
"A": parseWeekday,
"b": parseShortMonth,
"B": parseMonth,
"c": parseLocaleDateTime,
"d": parseDayOfMonth,
"e": parseDayOfMonth,
"H": parseHour24,
"I": parseHour24,
"j": parseDayOfYear,
"L": parseMilliseconds,
"m": parseMonthNumber,
"M": parseMinutes,
"p": parsePeriod,
"S": parseSeconds,
"U": parseWeekNumberSunday,
"w": parseWeekdayNumber,
"W": parseWeekNumberMonday,
"x": parseLocaleDate,
"X": parseLocaleTime,
"y": parseYear,
"Y": parseFullYear,
"Z": parseZone,
"%": parseLiteralPercent
};
As you can see, it is missing: "f"
, "Q"
, "s"
, "V"
and "u"
.
Because of that, some users are facing issues when using just the default bundle. Two recent examples can be seen here and here (in this last one the user was incorrectly using "%L"
, but changing for "%f"
- which is the correct specifier - will return null
).
I don't know if this was intentional, but I don't think so.
Cheers,
Related d3/d3-format#22.
Hi,
The last version of this package (2.2.1) is having errors in angular production build. Before this package d3-color had the same exact problem in prod build.
I don't know what's happening but it's making our app unstable. This is the second time in less than a month that it's happening in d3 package.
The error now that we are facing is this:
t.timeFormat is not a function
Hello,
I work for a data science company and one of our subsidiaries is trying to raise awareness through building a dashboard application that we will possibly put online.
May I use this? Can you share the input data? http://bl.ocks.org/gisminister/10001728
I plan to use it to show # cases/ deaths/recovered by region for different areas. I have global data also.
You do not share your dataset and I understand why, but I would love to have your assistance by sharing the input data so I can update it with the #cases data. I will happily cite you in this tool and if it is used in our public website I will make sure you're known as a contributor.
I have no budget to buy this, there's no money here. We are just trying to raise awareness through a hackathon competition and the winner's tool will possibly be used on the public site to help educate people about the virus.
My personal email is [email protected] or AnthonyMele.sumitovant.com and my phone is 9739785509.
Please let me know if you can share the data. you have made a beautiful visualization and I am very impressed by the clustering pie charts. May I use your code and have your full permission to use it for non-profit purposes.
Thank you,
Tony Mele
From http://man7.org/linux/man-pages/man3/strftime.3.html:
The ISO 8601 week number (see NOTES) of the current year as a decimal number, range 01 to 53, where week 1 is the first week that has at least 4 days in the new year.
And:
%G, %g, and %V yield values calculated from the week-based year defined by the ISO 8601 standard. In this system, weeks start on a Monday, and are numbered from 01, for the first week, up to 52 or 53, for the last week. Week 1 is the first week where four or more days fall within the new year (or, synonymously, week 01 is: the first week of the year that contains a Thursday; or, the week that has 4 January in it). When three of fewer days of the first calendar week of the new year fall within that year, then the ISO 8601 week-based system counts those days as part of week 53 of the preceding year. For example, 1 January 2010 is a Friday, meaning that just three days of that calendar week fall in 2010. Thus, the ISO 8601 week-based system considers these days to be part of week 53 (%V) of the year 2009 (%G); week 01 of ISO 8601 year 2010 starts on Monday, 4 January 2010.
Related d3/d3#2151.
Also note that #7 (d3/d3#1811) proposes using %V for the signed year, but it seems like consistency with strftime is preferable.
With #4, we can now parse four time zone offset formats:
However, we can only format two of these (the first using %Z
, and the last using a literal Z
). It would be nice to format the other two as well, but I’m unsure how to represent these in the format syntax. Perhaps ±hh could be a new (lowercase) z
directive, which behaves identically to Z
when parsing (akin to e
& d
, H
& I
)?
Per Ruby strftime:
%s
is seconds since UNIX epoch%Q
is milliseconds since UNIX epochRun this code:
d3.timeParse('%Y-%m-%dT%X')('2014-09-25T00:00:00');
will be return null;
But I replace '%X' with '%H:%M:%S' , it work
I'm having trouble importing d3-time-format.
I'm using browserify and npm and my code looks like:
import d3 from 'd3';
import timeFormat from 'd3-time-format';
...
var parseDate = d3.timeFormat('%b-%y'); // Error happens here
Later when I call d3.timeFormat it gives an error of undefined
Cannot read property 'timeFormat' of undefined
Version 3.0.0
import * as tf from 'd3-time-format';
console.log(tf.timeParse("%m/%d/%y")("66/8/20"));
==>
2025-06-07T22:00:00.000Z
Would rather expect null.
What am I missing?
Tx!
Peter
The same method was working in 2.2.1 version.
Now after the new release it broke.
Hello,perhaps d3-time-format does not support [email protected],logs follow:
The package [email protected] does not satisfy its siblings' peerDependencies requirements!
npm ERR! peerinvalid Peer [email protected] wants react@^0.14.7
npm ERR! peerinvalid Peer [email protected] wants react@^0.14.1
npm ERR! peerinvalid Peer [email protected] wants react@^0.14.7
npm ERR! peerinvalid Peer [email protected] wants react@^0.14.0
if a sane person formats a time they would very often want to have 3:15 p.m.
instead of 03:15 p.m.
. sadly this was never possible with d3.timeFormat. I think it's about time to add it.
Using Sunday-based week and day-of-week numbers, the format and parse methods treat week zero inconsistently. This can cause round-tripping of a date to fail. Based on the documentation, my understanding is that week one commences with the first Sunday of the year, and days prior to that lie in week zero. If so, it looks like the format method is buggy.
d3.timeFormat('%Y %U %w')(new Date(2012, 0, 1)) // "2012 00 0" -> should be "2012 01 0"?
d3.timeParse('%Y %U %w')('2012 00 0').toLocaleString() // "12/25/2011, 12:00:00 AM"
d3.timeParse('%Y %U %w')('2012 01 0').toLocaleString() // "1/1/2012, 12:00:00 AM"
d3.utcFormat('%Y %U %w')(new Date(Date.UTC(2012, 0, 1))) // "2012 00 0"
d3.utcParse('%Y %U %w')('2012 00 0').toUTCString() // "Sun, 25 Dec 2011 00:00:00 GMT"
Using Monday-based week and day-of-week numbers exhibits the same problem:
d3.timeFormat('%Y %W %u')(new Date(2018, 0, 1)) // "2018 00 1" -> should be "2018 01 1"?
d3.timeParse('%Y %W %u')('2018 00 1').toLocaleString() // "12/25/2017, 12:00:00 AM"
d3.timeParse('%Y %W %u')('2018 01 1').toLocaleString() // "1/1/2018, 12:00:00 AM"
d3.utcFormat('%Y %W %u')(new Date(Date.UTC(2018, 0, 1))) // "2018 00 1"
d3.utcParse('%Y %W %u')('2018 00 1').toUTCString() // "Mon, 25 Dec 2017 00:00:00 GMT"
Related d3/d3#495. TODO:
%o
)This implementation works in English:
var suffixes = ["th", "st", "nd", "rd"];
function suffix(number) {
var tail = number % 100;
return suffixes[(tail < 11 || tail > 13) && (tail % 10)] || suffixes[0];
}
However, it’s not clear how we should localize this behavior. Perhaps the locale definition can include a JavaScript function?
It might be a little cleaner if time parsers were constructed separately from formatters. In most cases, I end up doing something like this:
var parseTime = d3.timeFormat("%x").parse;
How about this instead:
var parseTime = d3.timeParser("%x");
Though, the asymmetry between “format” (which can be both a noun and a verb), “formatter”, “parse” (which can only be a verb) and “parser” bothers me.
Like:
Jan, Feb, Mar = 1
Apr, May, June = 2
and so on.
Given %Q
is taken, perhaps %q
?
I have an application that's parsing date strings with a format that includes %Z
like in the example below:
import { utcFormat, utcParse } from 'd3-time-format';
const dateFormat = '%Y-%m-%dT%H:%M:%S%Z';
const dateParser = utcParse(dateFormat);
const dateFormatter = utcFormat(dateFormat);
let dateString = '2017-09-15T06:00:00+00:00';
let dateObject = new Date(dateString);
let parsedDate = dateParser(dateString);
let formattedDateString = dateFormatter(parsedDate);
let newDateObject = new Date(formattedDateString);
let newParsedDate = dateParser(formattedDateString);
The formattedDateString
is equal to 2017-09-15T06:00:00+0000
as expected given the return value of the formatZone
function (https://github.com/d3/d3-time-format/blob/master/src/locale.js#L523)
function formatUTCZone() {
return "+0000";
}
The trouble is that in the above code newDateObject
has the expected Date value in Chrome/Firefox/Edge, but is a Date which is flagged as an invalid date
in Safari or IE11.
I need to pass date strings to a library that then converts them to Date objects, and I'm using utcHour
from d3-time
to generate some of the date strings. Given those constraints I was able to work around this problem using the following code instead of just calling dateFormatter(date)
directly:
let formatAndFixZone = date => dateFormatter(date).replace('+0000', '+00:00'); // Safari/IE11 fix for default d3 timezone formatting.
TLDR; In Safari and IE11 the Date constructor requires the timezones to be formatted with a :
(colon) to be able to parse from date strings.
I get that this is probably a minor concern for d3, since utcParse
exists (and local variants as well), but I was curious to know if there was a strong reason for not changing the default formatting to format time zones as +00:00
instead of +0000
. This would allow ISO 8601 date strings to be generated with d3-time-format
in a way that could be natively parsed in all browsers.
I’m currently considering the long-term plan for this library.
JavaScript’s native support for localized date and time formatting has improved dramatically since D3 was first created (and pv.Format.time in Protovis before that). In particular, the fact that date.toLocaleString automatically uses the browser’s current locale is such a huge improvement (less en-US-centric) that I feel promoting d3-time-format’s continued use is harmful.
https://observablehq.com/@mbostock/date-formatting
There is also a nice standard for relative time format, Intl.RelativeTimeFormat:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RelativeTimeFormat
It hasn’t made it to Edge and Safari yet, but Edge will eventually be Chromium, and Safari will hopefully come around. I expect therefore it would be better to encourage adoption of the standard and perhaps offer a polyfill than to compete with the proposed standard.
I was just evaluating various "time ago" libraries, such as https://github.com/hustcc/timeago.js and https://github.com/nmn/react-timeago , and it occurred to me that a formatter using the ago format would probably be straightforward to construct using d3-time-format.
Might it be of interest to include an ago
formatting method as part of d3-time-format?
Returning an update interval in ms would also be a useful counterpart, for updating the string.
format expects a date, but it doesn’t coerce the input to a date before formatting.
parse expects a string, but it doesn’t coerce the input to a string before parsing.
Related d3/d3#2543.
Replicate: In Chrome, use scaleTime()
with d3.axis{whichever}
and default tick settings, and set the domain to [new Date(1883, 10), new Date(1883, 11)]
.
Expected: The automatic ticks work normally
Actual: Before Mon 19, tickFormat
returns :00
only
AFAICT this is due to:
"Chrome has implemented a new spec for timezone offset calculation following the merge of Make LocalTZA take 't' and 'isUTC' and drop DSTA(t) to Ecma 262. So now the time-zone conversion does not work by just backward interval of seconds, it is calculated as what local time was being observed in a specific region" Source
Although Chrome is currently the only browser with this issue (well, difference), it will eventually be adopted by other browsers.
I poked around through the source and I'm guessing the problem lies in the interval measurements, but I can't tell why. Ideas?
In the meantime I can implement my own formatter, but I hate duplicated effort :p
There is currently no way to format the era when attempting to render B.C./BCE or pre-1000 years.
For the sake of expediency, an era flag should only yield "BCE" or "CE", since these both come after the year, but A.D. is supposed to proceed it.
First, does d3 conform to ISO 8601 or the XSD variant for BCE dates? That is to say, ISO 8601 dictates that "0000" is 1 BCE, "-0010" is 11 BCE. XSD is more compatible with direct integer representations, so "-0001" is 1 BCE, and "0000" is an invalid xsd:gYear.
With that said, I have attempted to format "0010" (10 CE) as "%Y", and the output is still "0010". Furthermore, there is no flag for era ("%E" would be nice), so "-0010" cannot be designated as BCE).
Ideally, "%Y" should convert a 4-character ISO date into an integer, so that a source xsd:gYear of "-0050" can be formatted with "%Y %E" into "50 BCE"
Basically I am wondering if there is a non-hacky way in d3 time format to show localized pair of Hours:Minutes (to get 18:03 in German locale and 6:03 PM in US locale)
As I see, moment.js has something like
longDateFormat : {
LT : 'HH:mm', // <----- this is what I can not find in D3.js
LTS : 'HH:mm:ss',
L : 'DD/MM/YYYY',
LL : 'D MMMM YYYY',
LLL : 'D MMMM YYYY HH:mm',
LLLL : 'dddd D MMMM YYYY HH:mm'
},
I do not suggest to mimic moment behavior, but time without seconds is pretty useful for time charts, where seconds may not be useful. This localized hh:mm pair can be easily used in the localized multiFormat
function as formatHour
Parsing appears to entirely ignore the day of week.
d3.timeFormat("%a")(d3.timeParse("%a")("Wed")) // "Mon"
d3.timeFormat("%A")(d3.timeParse("%A")("Wednesday")) // "Monday"
d3.timeFormat("%w")(d3.timeParse("%w")("3")) // "1"
It's interesting to note that the tests for this include the full date so pass by virtue of the dates being parsed falling on those days and not because the day-of-week is being correctly parsed.
tape("timeParse(\"%a %m/%d/%Y\")(date) parses abbreviated weekday and date", function(test) {
var p = timeFormat.timeParse("%a %m/%d/%Y");
test.deepEqual(p("Sun 01/01/1990"), date.local(1990, 0, 1));
test.deepEqual(p("Wed 02/03/1991"), date.local(1991, 1, 3));
test.equal(p("XXX 03/10/2010"), null);
test.end();
});
It does appear to work in conjunction with %W or %U.
https://npm.runkit.com/d3-time-format
instead of
https://tonicdev.com/npm/d3-time-format
I can send a PR if you want me to.
Currently en-US uses the same time format as en-UK i.e. a 24h time format
https://github.com/d3/d3-time-format/blob/master/locale/en-US.json#L4
I believe most platforms would use a 12 hour time and AM/PM i.e. something closer to %I:%M:%S %p
for this culture and potentially a few others. Is this a deliberate choice?
It is impossible to parse timestamps like this 1553232410.535
- one would expect %s.%L
to do that, as that is the output of format()
for that specifier.
I've addressed this on our fork and is part of this PR: #44
Hi
I'm having a problem parsing UTC timestamps with 6 digits.
2016-10-06T20:32:56.523411Z
It works just fine with three digits.
I'm working with realtime data so it could be messy and heavy workaround to shorten this before parsing. And changes at the source could be hard to get trough.
A timestamp created by Python datetime.datetime.today().isoformat() outputs 2017-11-21T08:34:28.150206. When reading this in from file and parsing it with d3.utcParse("%Y-%m-%dT%H:%M:%S.%L"), I get an error since the fractional seconds part has six instead of three digits. Without knowing what the ISO standard really specifies there, it were nice if %L could either be more lenient and accept any number of consecutive digits, or the number of digits could be specified. This would save the effort of having to truncate/reformat the string before parsing it and would allow direct export/import of ISO datetime data.
Is this behavior expected?
var d3TimeFormat = require("d3-time-format")
d3TimeFormat.timeParse('%m/%d/%Y')('26/1/2017') // Fri Feb 01 2019 00:00:00 GMT+0900 (JST)
d3TimeFormat.timeParse('%d/%m/%Y')('26/1/2017') // Thu Jan 26 2017 00:00:00 GMT+0900 (JST)
I read from README %m - month as a decimal number [01,12].
, so I would like d3TimeFormat.timeParse('%m/%d/%Y')('26/1/2017')
to return null, is that possible?
Thank you.
The npm install correctly retrieves the build directory, but the bower only retrieves the source files as seen in the repository.
Some countries, like Brazil, using pt-BR locale, need a boolean flag to express "we only use 24hs, please never use periods"... Or at least "please avoid periods".
NOTES
Some softwares like VEGA-lite are accepting "periods": []
but without use 24hs, that is also wrong. Another way to create a new convention is to accept explicit null as this kind of convention... But it is not perfect, because the "periods" translation can be useful for interface where user must to use it. So, a flag as prefer-no-periods: true
is the better convention.
https://github.com/d3/d3-time-format/blob/master/locale/zh-CN.json#L7
it's currently:
"shortDays": ["周日", "周一", "周二", "周三", "周四", "周五", "周六"],
but this is a typo, it should be:
"shortDays": ["週日", "週一", "週二", "週三", "週四", "週五", "週六"],
reference: https://zh.wikipedia.org/wiki/%E6%98%9F%E6%9C%9F%E4%B8%80
ISO weekdays are Monday based and numbered 1-7, but d3 only provides %w
, which is Sunday based and numbered 0-6.
E.g. momentjs uses E
for ISO weekday.
Additionaly to %u and %V:
d3.timeFormat('%t')(new Date(2016, 0, 1)); // 2015
I want to display localized time on my X axis (dates). I create my locale definition, and call d3.timeFormatDefaultLocale(myLocaleDefinition)
. It works and is almost perfect, I can see localized names of days and months, but hours are in 12 hour time (AM and PM). Even though my locale uses 24 hour time, I was forced to include a "periods" property in my definition, or else I would get an error.
The default time formatter wants to use the 12 hour clock (it uses "%I %p" for hours). If I want to use a 24 hour clock (and omit the incorrect "periods" property from my locale definition), I have to create my own time formatter, right?
The problem is that this is too difficult. It took me 3 hours of reading the documentation and examples to even understand where the problem is and what a time formatter is. I could not find a single example of a locale definition that does not use "periods". I realized later that using "periods" is required. Why?
In the documentation Russian is used as an example, but I don't think russians use 12h clock! And when I check the list of locales, every single one of them uses periods. Do the Germans, Spanish, Italians, Czechs, French and Russians all use AM and PM? I am sure they don't, and if so, that property should not be there, and it should default to 24h clock or force the use of another property.
TL;DR I want to use 24h clock just from the locale definition, not by researching and creating an entire new time formatter, and being confused by strange examples
Thanks for your help and understanding.
Related d3/d3#1811.
There’s a related question as to how we would support years that have more or fewer than four digits.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.