标记时间错误(TImezone?)
Time in marker wrong (TImezone?)
我用轻量级图表创建了这个漂亮的图表。
我现在面临的问题是,在 x 轴上的标记(灰色工具提示)中,显示的时间似乎偏移了 2 小时。
我感觉这是一个时区问题,因为我是 CEST,也就是 UTC+2,但我不知道这是怎么发生的,在哪里发生的,也不知道如何解决。
这是生成图表部分的Vue SFC的代码
<template>
<v-container
fluid
id="chart"
>
<v-btn-toggle
v-model="interval"
tile
group
@change="refresh"
>
<v-btn value="day">
Intraday
</v-btn>
<v-btn value="week">
Woche
</v-btn>
<v-btn value="month">
Monat
</v-btn>
<v-btn value="year">
Jahr
</v-btn>
<v-btn value="fiveyears">
5 Jahre
</v-btn>
</v-btn-toggle>
<Alert
:message="errorMessage"
type="error"
></Alert>
</v-container>
</template>
<script>
import { createChart, TickMarkType } from 'lightweight-charts';
import ChartService from '@/service/ChartService'
import Alert from '@/components/Alert'
import FormatterService from "../../service/FormatterService";
export default {
name: "ShareChart",
components: {
Alert
},
props: [
'quote',
'bus'
],
data() {
return {
errorMessage: '',
chart: null,
interval: 'day',
series: null,
format: null
}
},
methods: {
create() {
const chart = createChart(
document.getElementById('chart'),
{
height: 200,
localization: {
locale: 'de-DE',
dateFormat: 'dd.MM.yyyy',
priceFormatter: price => this.format.eur(price)
},
handleScale: false,
handleScroll: false
});
chart.applyOptions({
timeScale: {
timeVisible: true,
tickMarkFormatter: (time, tickMarkType) => {
time = new Date(time*1000)
let opt = {}
switch(tickMarkType) {
case TickMarkType.Year:
opt = {
year: 'numeric'
}
break
case TickMarkType.Month:
opt = {
month: 'short'
}
break
case TickMarkType.DayOfMonth:
opt = {
day: '2-digit'
}
break
case TickMarkType.Time:
opt = {
hour: '2-digit',
minute: '2-digit'
}
break
case TickMarkType.TimeWithSeconds:
opt = {
hour: '2-digit',
minute: '2-digit',
seconds: '2-digit'
}
}
return time.toLocaleString('de-DE', opt)
},
},
})
this.chart = chart
},
async getData() {
let res = null
try {
res = await ChartService.get(
this.interval,
{
isin: this.quote.isin,
date: new Date().toISOString(),
currency: this.quote.currency,
mic: this.quote.mic
}
)
} catch (e) {
this.errorMessage = e
return null
}
return res.quotes
},
draw(datasets) {
if(!this.chart) return
if(!datasets) return
if (this.series) this.chart.removeSeries(this.series);
this.series = this.chart.addAreaSeries()
let chartData = []
for(let ds of datasets) {
chartData.push({
time: new Date(ds.date).getTime()/1000,
value: ds.value
})
}
this.series.setData(chartData)
this.setAreaColors(datasets[0].value, datasets[datasets.length-1].value)
this.setTimeRange()
},
setAreaColors(open, close) {
let red = 0
let green = 200
if(open > close) {
red = 250
green = 0
}
this.series.applyOptions({
lineColor: 'rgb('+red+', '+green+', 0)',
topColor: 'rgba('+red+', '+green+', 0, 1)',
bottomColor: 'rgba('+red+', '+green+', 0, 0)'
});
},
setTimeRange() {
if(this.interval != 'day') {
return this.chart.timeScale().fitContent()
}
const fromTime = new Date()
fromTime.setHours(8, 0, 0)
const toTime = new Date()
toTime.setHours(20, 0, 0)
// TODO: Ignores timezones
this.chart.timeScale().setVisibleRange({
from: fromTime.getTime() / 1000,
to: toTime.getTime() / 1000,
});
},
async refresh() {
const quotes = await this.getData()
this.draw(quotes)
}
},
mounted() {
this.format = new FormatterService({
currency: this.quote.currency
})
this.create()
this.refresh()
},
watch: {
quote: function () {
this.refresh()
}
}
}
</script>
<style scoped>
</style>
setTimeRange() 函数的目的是将 'intraday' 图表的可见时间范围设置为当地时间上午 8 点到晚上 8 点。如果在那个时间范围内没有任何数据,它应该显示白色 space,这也不起作用。
有人可以帮忙吗?
感谢@timocov 将我指向 a related issue on the projects github。原来这是一个已知错误。
我是这样解决的:
chart.applyOptions({
timeScale: {
timeVisible: true,
tickMarkFormatter: (time, tickMarkType) => {
time = this.getTimezoneCorrectedTime(time)
[
...]
}
}
})
getTimezoneCorrectedTime(utcTime, returnAsUnixTimestamp = false) {
if(utcTime instanceof Date) {
utcTime = utcTime.getTime()/1000
}
const timezoneOffsetMinutes = new Date().getTimezoneOffset()
const correctedTime = utcTime+(timezoneOffsetMinutes*60)
if(returnAsUnixTimestamp) return correctedTime
return new Date(correctedTime*1000)
}
我用轻量级图表创建了这个漂亮的图表。
我现在面临的问题是,在 x 轴上的标记(灰色工具提示)中,显示的时间似乎偏移了 2 小时。
我感觉这是一个时区问题,因为我是 CEST,也就是 UTC+2,但我不知道这是怎么发生的,在哪里发生的,也不知道如何解决。
这是生成图表部分的Vue SFC的代码
<template>
<v-container
fluid
id="chart"
>
<v-btn-toggle
v-model="interval"
tile
group
@change="refresh"
>
<v-btn value="day">
Intraday
</v-btn>
<v-btn value="week">
Woche
</v-btn>
<v-btn value="month">
Monat
</v-btn>
<v-btn value="year">
Jahr
</v-btn>
<v-btn value="fiveyears">
5 Jahre
</v-btn>
</v-btn-toggle>
<Alert
:message="errorMessage"
type="error"
></Alert>
</v-container>
</template>
<script>
import { createChart, TickMarkType } from 'lightweight-charts';
import ChartService from '@/service/ChartService'
import Alert from '@/components/Alert'
import FormatterService from "../../service/FormatterService";
export default {
name: "ShareChart",
components: {
Alert
},
props: [
'quote',
'bus'
],
data() {
return {
errorMessage: '',
chart: null,
interval: 'day',
series: null,
format: null
}
},
methods: {
create() {
const chart = createChart(
document.getElementById('chart'),
{
height: 200,
localization: {
locale: 'de-DE',
dateFormat: 'dd.MM.yyyy',
priceFormatter: price => this.format.eur(price)
},
handleScale: false,
handleScroll: false
});
chart.applyOptions({
timeScale: {
timeVisible: true,
tickMarkFormatter: (time, tickMarkType) => {
time = new Date(time*1000)
let opt = {}
switch(tickMarkType) {
case TickMarkType.Year:
opt = {
year: 'numeric'
}
break
case TickMarkType.Month:
opt = {
month: 'short'
}
break
case TickMarkType.DayOfMonth:
opt = {
day: '2-digit'
}
break
case TickMarkType.Time:
opt = {
hour: '2-digit',
minute: '2-digit'
}
break
case TickMarkType.TimeWithSeconds:
opt = {
hour: '2-digit',
minute: '2-digit',
seconds: '2-digit'
}
}
return time.toLocaleString('de-DE', opt)
},
},
})
this.chart = chart
},
async getData() {
let res = null
try {
res = await ChartService.get(
this.interval,
{
isin: this.quote.isin,
date: new Date().toISOString(),
currency: this.quote.currency,
mic: this.quote.mic
}
)
} catch (e) {
this.errorMessage = e
return null
}
return res.quotes
},
draw(datasets) {
if(!this.chart) return
if(!datasets) return
if (this.series) this.chart.removeSeries(this.series);
this.series = this.chart.addAreaSeries()
let chartData = []
for(let ds of datasets) {
chartData.push({
time: new Date(ds.date).getTime()/1000,
value: ds.value
})
}
this.series.setData(chartData)
this.setAreaColors(datasets[0].value, datasets[datasets.length-1].value)
this.setTimeRange()
},
setAreaColors(open, close) {
let red = 0
let green = 200
if(open > close) {
red = 250
green = 0
}
this.series.applyOptions({
lineColor: 'rgb('+red+', '+green+', 0)',
topColor: 'rgba('+red+', '+green+', 0, 1)',
bottomColor: 'rgba('+red+', '+green+', 0, 0)'
});
},
setTimeRange() {
if(this.interval != 'day') {
return this.chart.timeScale().fitContent()
}
const fromTime = new Date()
fromTime.setHours(8, 0, 0)
const toTime = new Date()
toTime.setHours(20, 0, 0)
// TODO: Ignores timezones
this.chart.timeScale().setVisibleRange({
from: fromTime.getTime() / 1000,
to: toTime.getTime() / 1000,
});
},
async refresh() {
const quotes = await this.getData()
this.draw(quotes)
}
},
mounted() {
this.format = new FormatterService({
currency: this.quote.currency
})
this.create()
this.refresh()
},
watch: {
quote: function () {
this.refresh()
}
}
}
</script>
<style scoped>
</style>
setTimeRange() 函数的目的是将 'intraday' 图表的可见时间范围设置为当地时间上午 8 点到晚上 8 点。如果在那个时间范围内没有任何数据,它应该显示白色 space,这也不起作用。
有人可以帮忙吗?
感谢@timocov 将我指向 a related issue on the projects github。原来这是一个已知错误。
我是这样解决的:
chart.applyOptions({
timeScale: {
timeVisible: true,
tickMarkFormatter: (time, tickMarkType) => {
time = this.getTimezoneCorrectedTime(time)
[
...]
}
}
})
getTimezoneCorrectedTime(utcTime, returnAsUnixTimestamp = false) {
if(utcTime instanceof Date) {
utcTime = utcTime.getTime()/1000
}
const timezoneOffsetMinutes = new Date().getTimezoneOffset()
const correctedTime = utcTime+(timezoneOffsetMinutes*60)
if(returnAsUnixTimestamp) return correctedTime
return new Date(correctedTime*1000)
}