读取没有时区的字符日期时间

Read character datetimes without timezones

我正在尝试在 R 中导入一个包含日期时间的文本文件。时间以字符格式存储,没有时区信息,但我们知道这是法国时间(Europe/Paris)。

时区更改日期出现问题:例如从 2018-10-28 03:00:00 CEST2018-10-28 02:00:00 CET 有一个时间变化,因此我们的字符格式有重复,R 无法判断它是 CEST 还是 CET.

考虑以下示例:

data_in <- "date,val
2018-10-28 01:30:00,25
2018-10-28 02:00:00,26
2018-10-28 02:30:00,27
2018-10-28 02:00:00,28
2018-10-28 02:30:00,29
2018-10-28 03:00:00,30"

library(readr)
data <- read_delim(data_in, ",", locale = locale(tz = "Europe/Paris"))

我们的日期重复了:

data$date
[1] "2018-10-28 01:30:00 CEST" "2018-10-28 02:00:00 CEST" "2018-10-28 02:30:00 CET"  "2018-10-28 02:00:00 CEST"
[5] "2018-10-28 02:30:00 CET"  "2018-10-28 03:00:00 CET" 

预期输出为:

data$date
[1] "2018-10-28 01:30:00 CEST" "2018-10-28 02:00:00 CEST" "2018-10-28 02:30:00 CEST"  "2018-10-28 02:00:00 CET"
[5] "2018-10-28 02:30:00 CET"  "2018-10-28 03:00:00 CET" 

知道如何解决这个问题(除了告诉人们使用 UTC 或 ISO 格式之外)。我想唯一的方法是假设日期是排序的,所以我们可以知道第一个是 CEST.

如果你确定你的时间总是在增加,那么你可以寻找明显的减少(一天中的时间)并手动将 TZ 偏移量插入字符串,然后像往常一样解析。我添加了一些逻辑来仅在凌晨 2 点到 3 点左右寻找这种下降,这样如果您有多天跨越午夜的数据,您就不会收到误报。

data <- read.csv(text = data_in)
fakedate <- as.POSIXct(gsub("^[-0-9]+ ", "2000-01-01 ", data$date))
decreases <- cumany(grepl(" 0[23]:", data$date) & c(FALSE, diff(fakedate) < 0))
data$date <- paste(data$date, ifelse(decreases, "+0100", "+0200"))
data
#                        date val
# 1 2018-10-28 01:30:00 +0200  25
# 2 2018-10-28 02:00:00 +0200  26
# 3 2018-10-28 02:30:00 +0200  27
# 4 2018-10-28 02:00:00 +0100  28
# 5 2018-10-28 02:30:00 +0100  29
# 6 2018-10-28 03:00:00 +0100  30

as.POSIXct(data$date, format="%Y-%m-%d %H:%M:%S %z", tz="Europe/Paris")
# [1] "2018-10-28 01:30:00 CEST" "2018-10-28 02:00:00 CEST" "2018-10-28 02:30:00 CEST"
# [4] "2018-10-28 02:00:00 CET"  "2018-10-28 02:30:00 CET"  "2018-10-28 03:00:00 CET" 

我对 "2000-01-01" 的使用只是一些非 DST 日,因此我们可以将时间戳解析为 POSIXt 并计算其差异。 (如果我们没有插入日期,我们仍然可以使用带有格式的 as.POSIXct,但是如果你曾经 运行 在夏令时的两个日期中的任何一天这样做,你可能会得到不同的结果,因为 as.POSIXct("01:02:03", format="%H:%M:%S") 总是假设 "today".

它的假设显然有点脆弱,但也许它足以满足您的需求。