需要读取某个时区的纪元时间,然后将其转换为用户时区

问题描述 投票:0回答:2

我有 2 个网络应用程序,其中 1 个在云上是“主”,我需要将第二个网络应用程序“子”中的日期与之匹配。

Master(第一个网络应用程序,云)正在显示亚洲/加尔各答 IST 的日期,它是从位于 EST 时区的 SQL 机器读取的。

Child(第二个 web 应用程序)从 Elasticsearch 读取数据,其中 java feeder 获取 sql 数据并将其按原样推送到 Elasticsearch,无需任何转换。

当我尝试在我的 web 应用程序(子)中读取此 Elasticsearch 数据时

...
{
    "_index": "log_event_2016-05-05",
    "_type": "log_event",
    "_id": "65708004",
    "_score": null,
    "_source": {
        "task_name": "kn_cvs_test",
        "task_start_time": "2016-05-05T19:05:05.000-07:00",
        "task_end_time": "2016-05-05T19:05:06.000-07:00",
        "started_by": "Schedule \"10Minutes\"",
        "log_datetime": 1462475106000,
        "dw_insert_dt": "2016-05-05T16:40:54.000-07:00"
    },
    "sort": [
        1462475106000
    ]
}, {
    "_index": "log_event_2016-05-05",
    "_type": "log_event",
    "_id": "65708005",
    "_score": null,
    "_source": {
        "task_name": "kn_cvs_test",
        "task_start_time": "2016-05-05T18:55:08.000-07:00",
        "task_end_time": "2016-05-05T18:55:11.000-07:00",
        "started_by": "Schedule \"10Minutes\"",
        "log_datetime": 1462474511000,
        "dw_insert_dt": "2016-05-05T16:40:54.000-07:00"
    },
    "sort": [
        1462474511000
    ]
}
...

我的网络应用程序和云中的日期不匹配。如果我错了,请纠正我。由于 Sql 以 EST“America/New_York”存储日期,Momentjs 应首先读取 EST 中的

data  = 1462475106000
,然后应用用户时区,即 IST“Asia/Kolkata”。这是正确的吗?

//Timestamp column in table
//data  = 1462475106000
$scope.getMeData = function(data) {
    var dFormat = "YYYY-MM-DD hh:mm:ss A";
    moment.tz.setDefault("America/New_York");       
    return moment.tz(data, "Asia/Kolkata").format(dFormat); 
}

注意:1462475106000 是两个表中的第一个条目

我在这里放了一个plunker。 请帮助我找出可能出现的问题以及如何匹配两个网络应用程序中的日期(以云为参考)。

更新

Java feeder 运行 SQL 查询来获取所有需要的列。以下是获取

log_datetime
的方法。这是正确的获取方式吗?

(task_end_time - to_date('1-1-1970 00:00:00','MM-DD-YYYY HH24:Mi:SS'))*24*3600*1000 AS "log_datetime"

所以我假设当它获取数据时不考虑夏令时信息,我也错过了这个信息。因此,在 UI 方面,我将检查 isDST() 并根据它执行 +5:00 小时或 +4:00 小时,因为 sql 中的日期存储在

America/New_York
中。 修复 UI 的 Plunker

javascript jquery angularjs timezone momentjs
2个回答
5
投票

在任何时间任何地点都只有一个纪元时间。这是一个绝对值。

一个近似自纪元以来经过的秒数的值。协调世界时名称(以秒 (tm_sec)、分钟 (tm_min)、小时 (tm_hour)、自当年 1 月 1 日起的天数 (tm_yday) 和日历年减去 1900 (tm_year) 的形式指定)与时间相关根据下面的表达式,表示为自纪元以来的秒数。

参考http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_15

纪元时间是从

01-01-1970 00:00:00 UTC
开始测量的。这是一个绝对的瞬间,它与时区无关,因为时区
UTC
是纪元的定义。

每当您看到日期数字(例如您的示例

1462475106000
)时,都应假定它位于
UTC/GMT
中。它不是时区特定值。由于时间是基于 Unix 的数字,根据纪元定义,它是自纪元(UTC 格式)以来经过的时间,使其成为绝对时间。

(01-01-1970 00:00:00 UTC)(epoch) + 1462475106000 = Time in UTC

字符串中的日期完全是另一回事。它应该包括时区偏移量和日期部分。日期部分将被视为时区特定值。添加时区偏移量会将其转换为 UTC 的绝对值。如果没有时区信息,字符串日期就没有绝对值(时间点)。

2016-05-05T18:55:08.000-07:00 = (2016-05-05T18:55:08.000) + (07:00 hrs) UTC
or
date + timezone offset = date - offset hrs UTC

数据库不存储任何时区的日期。它们存储绝对的 Unix 时间值。设置数据库中的时区设置,以便字符串中的查询输出以该时区格式显示。此设置仅指定输出日期格式而不指定值。由于该值是绝对值,因此与时区无关。

如果用户错过了时区偏移量,此设置还可以帮助数据库确定用户插入的日期值的时区。如果用户尝试在没有时区的情况下在日期列中插入字符串,数据库将尝试将字符串默认为数据库时区设置。

所以

1462475106000
UTC
中的值,因为它是 Unix 时间。它不在
EST

如果您需要日期为

EST
,请使用字符串格式的日期而不是数字格式,因为数字格式始终为
UTC

moment.tz.setDefault("America/New_York");//sets the output date format in EST

上面的代码不会有任何效果,因为它被

moment.tz(data, "Asia/Kolkata")

覆盖

现在考虑第一个屏幕截图中的第一个条目。

2016-05-06T04:35:06.000+5:30 (IST) = 2016-05-05T11:05:06.000-00:00 (UTC)

与第二张截图相比,由于两者的时差为 4 小时,如果绝对时间相同,第二张截图应该在

+01:30
时区。

2016-05-06T12:35:06.000+1:30 = 2016-05-05T11:05:06.000-00:00 (UTC)

然而,在孩子身上,价值是

2016-05-05T19:05:06.000-07:00 = 2016-05-06T02:05:06.000-00:00 (UTC)

这与上面两个值不同。有趣的事实是,只有子项

2016-05-05T19:05:06.000
中的日期部分在添加
IST
偏移量
+05:30
时才会成为第二个屏幕截图中的日期部分。

2016-05-06T12:35:06.00 - 2016-05-05T19:05:06.000 = 5:30 (IST offset)

将 Java feeder 代码留给

ElasticSearch
可能是罪魁祸首。

它没有将正确的日期-时区组合写入 ElasticSearch。尝试使用重载方法

getDate()
getDate(int columnIndex, 日历 cal) 在 JDBC 中。

有时 JDBC 驱动程序会丢失时区信息,导致日期存储在默认数据库时区中,使用

Calendar
可以解决这个问题。

书写日期也是如此。

void setDate(int parameterIndex, Date x, Calendar cal) 抛出 SQLException


0
投票

您只需将日期从美国/纽约转换为亚洲/加尔各答(亚洲/加尔各答)?

var newYork    = moment.tz("date-from-database", "America/New_York");
var calcutta   = newYork.clone().tz("Asia/Calcutta");

示例

var newYork    = moment.tz("2016-05-06 12:00:00", "America/New_York");
var losAngeles = newYork.clone().tz("America/Los_Angeles");
var london     = newYork.clone().tz("Europe/London");
var Kolkata     = newYork.clone().tz("Asia/Kolkata"); 
var dFormat = "YYYY-MM-DD hh:mm:ss A";
console.log(newYork.format(dFormat),losAngeles.format(dFormat),london.format(dFormat),Kolkata.format(dFormat));

小提琴

© www.soinside.com 2019 - 2024. All rights reserved.