This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Chart v3.0.0: Time Cartesian Axis - w/o Date Adapters ??? #8771
Comments
I don't really understand what the issue is.
|
Yes
Yes, but i do not know how i can use the formatted timestamp with the
?? This is my simple way to format the timestamp /**
* get date format
* @param {string} date
* @param {string} format
* @returns
*/
function formatdate(date, format = "Y-m-d") {
const groupFormats = {
minute: "Y-m-d H:s",
hour: "Y-m-d H:00",
day: "Y-m-d 00:00",
month: "Y-m-01 00:00",
year: "Y-12-31 00:00"
}
format = groupFormats[format] || format || "Y-m-d"
date = new Date(date)
const hour24 = date.getHours()
const hour12 = date.getHours() % 12 || 12
const numDay = date.getDay()
const numMonth = date.getMonth()
const parts = {
Y: date.getFullYear().toString(),
y: ("00" + (date.getYear() - 100)).toString().slice(-2),
m: ("0" + (numMonth + 1)).toString().slice(-2),
n: (numMonth + 1).toString(),
d: ("0" + date.getDate()).toString().slice(-2),
j: date.getDate().toString(),
H: ("0" + hour24).toString().slice(-2),
h: ("0" + hour12).toString().slice(-2),
G: hour24.toString(),
g: hour12.toString(),
a: hour24 >= 12 && hour24 < 24 ? "pm" : "am",
A: hour24 >= 12 && hour24 < 24 ? "PM" : "AM",
i: ("0" + date.getMinutes()).toString().slice(-2),
s: ("0" + date.getSeconds()).toString().slice(-2),
w: numDay,
N: numDay > 0 ? numDay : 7,
D: localeNames.days_short[numDay],
l: localeNames.days_long[numDay],
M: localeNames.month_short[numMonth],
F: localeNames.month_long[numMonth]
}
const modifiers = Object.keys(parts).join("")
const reDate = new RegExp("[" + modifiers + "]", "g")
const dt = format.replace(reDate, ($0) => parts[$0])
return dt
} |
So you are constructing the localeNames based on locale? You could just create a custom adapter. |
the performance of Intl.DateTimeFormat is not very good, I load the translations when the locale is changed in order to use them later for the DateFormat. /**
* get the localized day and month names
* @param {str} locale
* @returns list
*/
function getLocaleNamesCached(localeName = "at-DE") {
const datetext = {
days_short: [...Array(7).keys()].map((day) =>
new Intl.DateTimeFormat(localeName, { weekday: "short" }).format(new Date(Date.UTC(2021, 5, day)))
),
days_long: [...Array(7).keys()].map((day) =>
new Intl.DateTimeFormat(localeName, { weekday: "long" }).format(new Date(Date.UTC(2021, 5, day)))
),
month_short: [...Array(12).keys()].map((month) =>
new Intl.DateTimeFormat(localeName, { month: "short" }).format(new Date(Date.UTC(2021, month, 1)))
),
month_long: [...Array(12).keys()].map((month) =>
new Intl.DateTimeFormat(localeName, { month: "long" }).format(new Date(Date.UTC(2021, month, 1)))
)
}
return datetext
}
const localeNames = getLocaleNamesCached(userLocale)
Yes, an alternative would be, but I don't (yet) understand the settings / methods of the date adapter.
I like it 👍, would be a simple implementation, but don't know the restrictions yet? But would be the preferred method for me. Here is an example of how I prepare the data: [
{
"x": 1617253200000,
"y": 0.117,
"localedate": "Fr, 01 Apr 21 07:07"
},
{
"x": 1617256800000,
"y": 0.249,
"localedate": "Fr, 01 Apr 21 08:21"
},
{
"x": 1617260400000,
"y": 2.068,
"localedate": "Fr, 01 Apr 21 09:35"
},
{
"x": 1617264000000,
"y": 2.685,
"localedate": "Fr, 01 Apr 21 10:49"
},
{
"x": 1617267600000,
"y": 2.666,
"localedate": "Fr, 01 Apr 21 11:04"
},
{
"x": 1617271200000,
"y": 2.565,
"localedate": "Fr, 01 Apr 21 12:18"
},
{
"x": 1617274800000,
"y": 2.567,
"localedate": "Fr, 01 Apr 21 13:37"
},
{
"x": 1617278400000,
"y": 2.552,
"localedate": "Fr, 01 Apr 21 14:51"
},
{
"x": 1617282000000,
"y": 1.776,
"localedate": "Fr, 01 Apr 21 15:06"
},
{
"x": 1617285600000,
"y": 1.669,
"localedate": "Fr, 01 Apr 21 16:20"
},
{
"x": 1617289200000,
"y": 1.251,
"localedate": "Fr, 01 Apr 21 17:34"
},
{
"x": 1617292800000,
"y": 0.3,
"localedate": "Fr, 01 Apr 21 18:49"
},
{
"x": 1617296400000,
"y": 0.069,
"localedate": "Fr, 01 Apr 21 19:58"
},
{
"x": 1617339600000,
"y": 0.16,
"localedate": "Sa, 02 Apr 21 07:57"
},
{
"x": 1617343200000,
"y": 0.325,
"localedate": "Sa, 02 Apr 21 08:16"
},
{
"x": 1617346800000,
"y": 0.544,
"localedate": "Sa, 02 Apr 21 09:30"
},
{
"x": 1617350400000,
"y": 2.59,
"localedate": "Sa, 02 Apr 21 10:44"
},
{
"x": 1617354000000,
"y": 2.627,
"localedate": "Sa, 02 Apr 21 11:03"
},
{
"x": 1617357600000,
"y": 2.647,
"localedate": "Sa, 02 Apr 21 12:15"
}
] |
Is the slow performance of |
Negativ cached formatter is also slow. |
Bad news, I can use your example statically and it works. Unfortunately, if I create the options with Javascript, I cannot add a callBack function: options.scales = _options.scales || {}
options.scales.x = _options.scales.x || {}
options.scales.x.type = "linear"
options.scales.x.ticks = _options.scales.x.ticks || {}
options.scales.x.ticks = {
callback: function(value, index, values) {
return new Date(value).toLocaleString()
}
}
options.scales.y = _options.scales.y || {}
options.scales.y.type = "linear" |
That is not a limitation of javascript or Chart.js. Why can't you add a callback? |
@kurkle Yes you are right, it was my mistake. It works now, but I don't yet know how to access the In the /**
* format the x-axis date/time label
* @param {*} value
* @param {*} index
* @param {*} values
* @returns
*/
const xAxisFormat = (value, index, values) => {
// TODO: how to get this from the options ???
const formatPattern = "longdate" // just for testing
if (Number.isInteger(values[index].value)) {
return formatdate(+values[index].value, formatPattern)
}
return values[index].value
}
options.scales = _options.scales || {}
options.scales.x = _options.scales.x || {}
options.scales.x.type = "time"
options.scales.x.time = {
unit: this.card_config.datascales.unit,
displayFormats: {},
}
options.scales.x.ticks = { callback: xAxisFormat } Works only for options.scales.x.type = "time" not for options.scales.x.type = "linear" |
Take a look at the default formatters (assigned as callback):
|
Negativ
|
arrow functions don't receive this. |
Sorry,
Tooltip /**
* format the tooltip label
* @param {*} context
* @returns string
*/
const formatToolTipLabel = (context) => {
let label = context.dataset.label || ""
const data = context.raw
const unit = context.dataset.unit ? ` (${context.dataset.unit})` : ""
label += ": " + context.formattedValue + unit
return label
} Works with
|
I have not found a way to access the const xAxisFormat = (tickValue, index, ticks) => {
const dateFormatPattern = "day" // no way to get this from the options !
if (Number.isInteger(ticks[index].value)) {
return formatdate(+ticks[index].value, dateFormatPattern)
}
return tickValue
} So the only possibility is to create your own adapter with which the date is displayed in the user language. Disadvantage:
Modified date-fn custom adapter import { _adapters } from "chart.js";
import {parse,parseISO,toDate,isValid,startOfSecond,startOfMinute,startOfHour,startOfDay,
startOfWeek,startOfMonth,startOfQuarter,startOfYear,addMilliseconds,addSeconds,
addMinutes,addHours,addDays,addWeeks,addMonths,addQuarters,addYears,differenceInMilliseconds,
differenceInSeconds,differenceInMinutes,differenceInHours,differenceInDays,differenceInWeeks,
differenceInMonths,differenceInQuarters,differenceInYears,endOfSecond,endOfMinute,endOfHour,
endOfDay,endOfWeek,endOfMonth,endOfQuarter,endOfYear,
} from "date-fns";
const FORMATS = {
default: "ddd, d mmmm yyyy HH:MM:ss.l",
shortDate: "m.d.yy",
mediumDate: "d.m.yyyy",
longDate: "d mmmm yyyy",
fullDate: "dddd, d mmmm yyyy",
shortTime: "H:MM",
mediumTime: "H:MM:ss",
longTime: "H:MM:ss.L",
isoDate: "yyyy-mm-dd",
isoTime: "HH:MM:ss",
isoDateTime: "yyyy-mm-dd'T'HH:MM:ss",
isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'",
week: "W",
quater: "Q",
datetime: "ddd, d mmmm yyyy HH:MM:ss",
millisecond: "H:MM:ss l",
second: "h:mm:ss l",
minute: "h:mm l",
hour: "H",
day: "d mmm",
month: "mmm yyyy",
year: "yyyy"
};
* Get week number in the year.
* @param {Integer} [weekStart=0] First day of the week. 0-based. 0 for Sunday, 6 for Saturday.
* @return {Integer} 0-based number of week.
*/
Date.prototype.getWeek = function (weekStart = 1) {
var januaryFirst = new Date(this.getFullYear(), 0, 1)
weekStart = weekStart || 0
return Math.floor(((this - januaryFirst) / 86400000 + januaryFirst.getDay() - weekStart) / 7)
}
/*
* Date Format 1.2.3
* (c) 2007-2009 Steven Levithan <stevenlevithan.com>
* MIT license
*
* Includes enhancements by Scott Trenda <scott.trenda.net>
* and Kris Kowal <cixar.com/~kris.kowal/>
*
* Accepts a date, a mask, or a date and a mask.
* Returns a formatted version of the given date.
* The date defaults to the current date/time.
* The mask defaults to dateFormat.masks.default.
* see: https://stevenlevithan.com/assets/misc/date.format.js
* https://blog.stevenlevithan.com/archives/date-time-format
* modified for chart.js
*/
var formatdate = (function () {
const token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZWQw]|"[^"]*"|'[^']*'/g,
timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,
timezoneClip = /[^-+\dA-Z]/g,
pad = function (val, len) {
val = String(val)
len = len || 2
while (val.length < len) val = "0" + val
return val
}
return function (date, mask, utc) {
const dF = formatdate
if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) {
mask = date
date = undefined
}
date = date ? new Date(date) : new Date()
if (isNaN(date)) throw SyntaxError("invalid date")
mask = String(dF.masks[mask] || mask || dF.masks["default"])
// Allow setting the utc argument via the mask
if (mask.slice(0, 4) == "UTC:") {
mask = mask.slice(4)
utc = true
}
const _ = utc ? "getUTC" : "get",
d = date[_ + "Date"](),
D = date[_ + "Day"](),
m = date[_ + "Month"](),
y = date[_ + "FullYear"](),
H = date[_ + "Hours"](),
M = date[_ + "Minutes"](),
s = date[_ + "Seconds"](),
L = date[_ + "Milliseconds"](),
o = utc ? 0 : date.getTimezoneOffset(),
flags = {
// day
d: d,
dd: pad(d),
ddd: window.localeNames.days_short[D],
dddd: window.localeNames.days_long[D],
// week
W: date.getWeek(1),
w: date.getWeek(0),
// month
m: m + 1,
mm: pad(m + 1),
mmm: window.localeNames.month_short[m],
mmmm: window.localeNames.month_long[m],
// year
yy: String(y).slice(2),
yyyy: y,
Q: "Q" + Math.floor(((date.getMonth() / 3) % 4) + 1),
// time hour
h: H % 12 || 12,
hh: pad(H % 12 || 12),
H: H,
HH: pad(H),
// time minute
M: M,
MM: pad(M),
// time seconds
s: s,
ss: pad(s),
// time Milliseconds
l: pad(L, 3),
L: pad(L > 99 ? Math.round(L / 10) : L),
// time am / pm
t: H < 12 ? "a" : "p",
tt: H < 12 ? "am" : "pm",
T: H < 12 ? "A" : "P",
TT: H < 12 ? "AM" : "PM",
// GMT/UTC timezone
Z: utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""),
o: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + (Math.abs(o) % 60), 4)
}
return mask.replace(token, function ($0) {
return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1)
})
}
})()
formatdate.masks = FORMATS;
_adapters._date.override({
_id: "date-fns",
formats: function () {
return FORMATS;
},
parse: function (value, fmt) {
if (value === null || typeof value === "undefined") {
return null;
}
const type = typeof value;
if (type === "number" || value instanceof Date) {
value = toDate(value);
} else if (type === "string") {
if (typeof fmt === "string") {
value = parse(value, fmt, new Date(), this.options);
} else {
value = parseISO(value, this.options);
}
}
return isValid(value) ? value.getTime() : null;
},
format: function (time, fmt) {
return formatdate(new Date(time), fmt);
},
add: function (time, amount, unit) {
switch (unit) {
case "millisecond":return addMilliseconds(time, amount);
case "second":return addSeconds(time, amount);
case "minute":return addMinutes(time, amount);
case "hour":return addHours(time, amount);
case "day":return addDays(time, amount);
case "week":return addWeeks(time, amount);
case "month":return addMonths(time, amount);
case "quarter":return addQuarters(time, amount);
case "year":return addYears(time, amount);
default:return time;
}
},
diff: function (max, min, unit) {
switch (unit) {
case "millisecond":return differenceInMilliseconds(max, min);
case "second":return differenceInSeconds(max, min);
case "minute":return differenceInMinutes(max, min);
case "hour":return differenceInHours(max, min);
case "day":return differenceInDays(max, min);
case "week":return differenceInWeeks(max, min);
case "month":return differenceInMonths(max, min);
case "quarter":return differenceInQuarters(max, min);
case "year":return differenceInYears(max, min);
default:return 0;
}
},
startOf: function (time, unit, weekday) {
switch (unit) {
case "second":return startOfSecond(time);
case "minute":return startOfMinute(time);
case "hour":return startOfHour(time);
case "day":return startOfDay(time);
case "week":return startOfWeek(time);
case "isoWeek":return startOfWeek(time, { weekStartsOn: +weekday });
case "month":return startOfMonth(time);
case "quarter":return startOfQuarter(time);
case "year":return startOfYear(time);
default:return time;
}
},
endOf: function (time, unit) {
switch (unit) {
case "second":return endOfSecond(time);
case "minute":return endOfMinute(time);
case "hour":return endOfHour(time);
case "day":return endOfDay(time);
case "week":return endOfWeek(time);
case "month":return endOfMonth(time);
case "quarter":return endOfQuarter(time);
case "year":return endOfYear(time);
default:return time;
}
},
}); I load the translations for the day and month names once when I start the application. /**
* set the local text for the day- and monthnames
*/
function getLocaleText(locale = "DE") {
return {
days_short: [...Array(7).keys()].map((day) =>
new Intl.DateTimeFormat(locale, { weekday: "short" }).format(new Date(Date.UTC(2021, 5, day)))
),
days_long: [...Array(7).keys()].map((day) =>
new Intl.DateTimeFormat(locale, { weekday: "long" }).format(new Date(Date.UTC(2021, 5, day)))
),
month_short: [...Array(12).keys()].map((month) =>
new Intl.DateTimeFormat(locale, { month: "short" }).format(new Date(Date.UTC(2021, month, 1)))
),
month_long: [...Array(12).keys()].map((month) =>
new Intl.DateTimeFormat(locale, { month: "long" }).format(new Date(Date.UTC(2021, month, 1)))
)
}
}
window.localeNames = getLocaleText(window.Chart3.defaults.locale) It would be much more performant and easier if the labels could be used in the dataset. If [
{
"x": 1616968800000,
"x-label": "2021-03-29",
"y": 0.24
},
{
"x": 1617055200000,
"x-label": "2021-03-30",
"y": 0.22
},
{
"x": 1617141600000,
"x-label": "2021-03-31",
"y": 2.86
},
{
"x": 1617228000000,
"x-label": "2021-04-01",
"y": 0.14
},
{
"x": 1617314400000,
"x-label": "2021-04-02",
"y": 0.21
},
{
"x": 1617400800000,
"x-label": "2021-04-03",
"y": 0.09
},
{
"x": 1617487200000,
"x-label": "2021-04-04",
"y": 0.25
}
] |
This is an arrow function, it is not bound and can not use const xAxisFormat = (tickValue, index, ticks) => {
const dateFormatPattern = "day" // no way to get this from the options !
if (Number.isInteger(ticks[index].value)) {
return formatdate(+ticks[index].value, dateFormatPattern)
}
return tickValue
} This is an traditional function and does not have the same limitations. It has the same name, so nothing else should need to be changed, unless something in your environment limits you from using normal/traditional functions? function xAxisFormat(tickValue, index, ticks) {
const dateFormatPattern = this.options.time.unit; // "day"
if (Number.isInteger(ticks[index].value)) {
return formatdate(+ticks[index].value, dateFormatPattern)
}
return tickValue
} |
@kurkle options.scales.x.ticks = { callback: xAxisFormat} |
@kurkle
|
Are you processing your package somehow? |
file: graphchart.js // -------------------
// just for testing...
// -------------------
if (window.configdata) {
_options.scales = _options.scales || {}
_options.scales.x = _options.scales.x || {}
_options.scales.x.type = "time"
_options.scales.x.time = {
unit: "day",
displayFormats: {}
}
_options.scales.x.ticks = {
callback: function (value, index, ticks) {
if(this){
console.log("THIS READY:",this)
return "OK " + value
}else{
console.log("THIS NOT PRESENT:",this)
return "FAILED " + value
}
}
}
} |
ok, so its the |
I thought you were going to use |
I think in your use case, it would be better (and faster) to override the Chart.js/src/scales/scale.time.js Lines 477 to 484 in 3943306
Chart.TimeScale.prototype.generateTickLabels = function(ticks) {
/* loop the ticks and set .label */
}; That could break when Chart.js v4 comes out, so should have a note about that in your code. |
An interesting approach, but it is too specific and not generally applicable. If the callback bug is fixed with I just think I'm not alone with the problem, it affects everyone who wants to display dates in their locale.
Has been fixed, no longer occurs in the current version. |
This is fixed by #8822, and will be available in 3.1 |
Thanks, works now. |
timeseries **
* format the x-axis date/time label
* @param {*} tickValue
* @param {*} index
* @param {*} ticks
* @returns formatted tick value
*/
function xAxisFormat(tickValue, index, ticks) {
console.log("xAxisFormat", this.options)
if (this && this.options.time && this.options.time.unit) {
const dateFormatPattern = this.options.time.unit
if (dateFormatPattern && Number.isInteger(ticks[index].value)) {
return formatdate(+ticks[index].value, dateFormatPattern)
}
}
return tickValue
} {
"type": "bar",
"data": {
"datasets": [
{
"label": "Verbrauch",
"unit": "kWh",
"minval": 0,
"maxval": 0,
"sumval": 0,
"avgval": 0,
"pointRadius": 0,
"current": -0.6300000000000001,
"last_changed": "2021-04-04T13:45:19.303440+00:00",
"mode": "history",
"backgroundColor": "#FF8066",
"data": [
{
"x": 1617055200000,
"localedate": "2021-03-30",
"y": -128.12
},
{
"x": 1617141600000,
"localedate": "2021-03-31",
"y": -160.55
},
{
"x": 1617228000000,
"localedate": "2021-04-01",
"y": -153.49
},
{
"x": 1617314400000,
"localedate": "2021-04-02",
"y": -142.32
},
{
"x": 1617400800000,
"localedate": "2021-04-03",
"y": -189.55
},
{
"x": 1617487200000,
"localedate": "2021-04-04",
"y": -75.08
}
]
},
{
"label": "Energieproduktion",
"unit": "kWh",
"minval": 0,
"maxval": 0,
"sumval": 0,
"avgval": 0,
"pointRadius": 0,
"current": 0,
"last_changed": "2021-04-04T13:45:17.876805+00:00",
"mode": "history",
"backgroundColor": "#fcec34",
"data": [
{
"x": 1617055200000,
"localedate": "2021-03-30",
"y": 99.891
},
{
"x": 1617141600000,
"localedate": "2021-03-31",
"y": 94.916
},
{
"x": 1617228000000,
"localedate": "2021-04-01",
"y": 106.155
},
{
"x": 1617314400000,
"localedate": "2021-04-02",
"y": 99.444
},
{
"x": 1617400800000,
"localedate": "2021-04-03",
"y": 73.143
},
{
"x": 1617487200000,
"localedate": "2021-04-04",
"y": 92.939
}
]
}
],
"labels": []
},
"options": {
"units": "",
"hoverOffset": 8,
"layout": {},
"interaction": {
"mode": "nearest",
"intersect": false
},
"chartArea": {
"backgroundColor": "transparent"
},
"elements": {},
"spanGaps": true,
"plugins": {
"title": {},
"tooltip": {
"callbacks": {}
},
"legend": {
"display": true,
"position": "top"
}
},
"animation": {},
"onResize": null,
"scales": {
"x": {
"axis": "x",
"type": "timeseries",
"ticks": {
"source": "auto",
"major": {
"enabled": false
},
"minRotation": 0,
"maxRotation": 50,
"mirror": false,
"textStrokeWidth": 0,
"textStrokeColor": "",
"padding": 3,
"display": true,
"autoSkip": true,
"autoSkipPadding": 3,
"labelOffset": 0,
"minor": {},
"align": "center",
"crossAlign": "near",
"color": "rgb(225, 225, 225)"
},
"alignToPixels": true,
"stacked": true,
"offset": true,
"title": {
"display": true,
"text": "Zeitraum",
"padding": {
"top": 4,
"bottom": 4
},
"color": "rgb(225, 225, 225)"
},
"grid": {
"offset": true,
"display": true,
"drawBorder": true,
"drawOnChartArea": true,
"drawTicks": true,
"tickLength": 8,
"borderDash": [
1,
1
],
"borderDashOffset": 0,
"borderColor": "rgb(2, 136, 209)",
"borderWidth": 0.88,
"color": "rgba(179, 229, 252, 0.8)"
},
"bounds": "data",
"adapters": {},
"display": true,
"reverse": false,
"beginAtZero": false,
"grace": 0,
"id": "x",
"position": "bottom"
},
"y": {
"axis": "y",
"alignToPixels": true,
"stacked": true,
"title": {
"display": true,
"text": "Energie kWh",
"padding": {
"top": 4,
"bottom": 4
},
"color": "rgb(225, 225, 225)"
},
"type": "linear",
"beginAtZero": true,
"ticks": {
"minRotation": 0,
"maxRotation": 50,
"mirror": false,
"textStrokeWidth": 0,
"textStrokeColor": "",
"padding": 3,
"display": true,
"autoSkip": true,
"autoSkipPadding": 3,
"labelOffset": 0,
"minor": {},
"major": {},
"align": "center",
"crossAlign": "near",
"color": "rgb(225, 225, 225)"
},
"display": true,
"offset": false,
"reverse": false,
"bounds": "ticks",
"grace": 0,
"grid": {
"display": true,
"drawBorder": true,
"drawOnChartArea": true,
"drawTicks": true,
"tickLength": 8,
"offset": false,
"borderDash": [
1,
1
],
"borderDashOffset": 0,
"borderColor": "rgb(2, 136, 209)",
"borderWidth": 0.88,
"color": "rgba(179, 229, 252, 0.8)"
},
"id": "y",
"position": "left"
}
}
}
}
|
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
Feature Proposal
I am looking for a way to use Time Cartesian Axis without a date adapter, because I have not found a way in the Home Assistant framework how I can use locale files for the adapter. Also I have my concerns, just to display the date / time in the user language, to use the date libs (moment, luxon, date-fn) for it.
I have different data sources that don't always have data for every time interval. It is possible to create a timeseries for Category Cartesian Axis for all data, but then my performance is poor, since many data always have 0 values.
Most likely I could use the chartjs-adapter-date-fns, but I can display the date and time in the user language.
What is my option?
The dataset contains the following data:
X-Axis: Date
Y-Axis: Value
Feature Use Case
Time axis Ticks label (x)
formatted andTooltips date / time
in the user language.Possible Implementation
???
The text was updated successfully, but these errors were encountered: