通过 Lubridate 转换日期字符串,月、日、年小时分钟 am/pm 和时区变化
Transform string in date through Lubridate with variation in month, day, year hour min am/pm and time zone
我需要一些有关不同时区润滑功能的帮助。我有两个这样的向量:
date1 = c("February 11th 2017, 6:05am PST", "April 24th 2018, 4:09pm PDT")
date2 = c("2013-12-14 00:58:00 CET", "2013-06-19 18:00:00 CEST")
我想使用 lubridate 函数(我试过 mdy_hm)将这些字符串转换为日期格式,然后在考虑时间差异的同时计算两个字符串的差异(以天为单位)时区,其中 PDT 中的 D 代表夏令时,PST 中的 S 代表太平洋时间的标准时区 (https://www.timeanddate.com/time/zones/pdt and https://www.timeanddate.com/time/zones/pst) and similarly for CET (https://time.is/CET) and CEST (https://time.is/CEST)。你能帮帮我吗?
我做的第一件事是用你的 2 个日期向量设置一个 tibble
tibble(
date1 = c("February 11th 2017, 6:05am PST", "April 24th 2018, 4:09pm PDT"),
date2 = c("2013-12-14 00:58:00 CET", "2013-06-19 18:00:00 CEST"),
) %>%
{. ->> my_dates}
my_dates
# # A tibble: 2 x 2
# date1 date2
# <chr> <chr>
# February 11th 2017, 6:05am PST 2013-12-14 00:58:00 CET
# April 24th 2018, 4:09pm PDT 2013-06-19 18:00:00 CEST
然后,列出时区缩写及其与 UTC 的偏移量
# setup timezones and UTC offsets
tribble(
~tz, ~offset,
'PST', -8,
'PDT', -7,
'CET', +1,
'CEST', +2
) %>%
{. ->> my_tz}
my_tz
# # A tibble: 4 x 2
# tz offset
# <chr> <dbl>
# PST -8
# PDT -7
# CET 1
# CEST 2
然后,我们通过删除 date1
中天数后面的字符后缀('11th' 之后的 'th' 位)来整理日期时间。我们还提取时区代码并将其放在单独的列中;时区列允许我们 left_join()
my_tz
,给我们 UTC 偏移量。
我们使用 stringr
package, and regex expressions to find, extract and replace the components. A very handy tool for testing regex patterns can be found here https://regex101.com/r/5pr3LL/1/
中的字符串处理函数
my_dates %>%
mutate(
# remove the character suffix after the day number (eg 11th)
day_suffix = str_extract(date1, '[0-9]+[a-z]+') %>% str_extract('[a-z]+'),
date1 = str_replace(date1, day_suffix, ''),
day_suffix = NULL,
# extract timezone info
date1_tz = str_extract(date1, '[a-zA-Z]+$'),
date2_tz = str_extract(date2, '[a-zA-Z]+$'),
) %>%
# join in timezones for date1
left_join(my_tz, by = c('date1_tz' = 'tz')) %>%
rename(
offset_date1 = offset
) %>%
# join in timezones for date2
left_join(my_tz, by = c('date2_tz' = 'tz')) %>%
rename(
offset_date2 = offset
) %>%
{. ->> my_dates_info}
my_dates_info
# # A tibble: 2 x 6
# date1 date2 date1_tz date2_tz offset_date1 offset_date2
# <chr> <chr> <chr> <chr> <dbl> <dbl>
# February 11 2017, 6:05am PST 2013-12-14 00:58:00 CET PST CET -8 1
# April 24 2018, 4:09pm PDT 2013-06-19 18:00:00 CEST PDT CEST -7 2
所以现在,我们可以使用lubridate::as_datetime()
将date1
和date2
转换为dttm
(日期时间)格式。 as_datetime()
采用字符格式的日期时间并将其转换为日期时间格式。您必须使用符号和缩写说明 here 指定字符串的格式。例如,这里我们使用%B
来表示月份的全称,%d
是天数,%Y
是(4位)年数等等。
注意:因为我们没有在 as_datetime()
内指定时区,所以与这些日期时间一起存储的基础时区默认为 UTC
(如使用 tz()
所示)。这就是我们将这些列称为 date*_orig
的原因,以提醒我们时区是原始日期时间的时区。然后我们将偏移量添加到 datetime 对象,所以我们现在有这些 UTC 时间(这些值的基础时区签名是 UTC
,所以这是理想的)。
# now define datetimes in local and UTC timezones (note: technically the tz is UTC for both)
my_dates_info %>%
mutate(
date1_orig = as_datetime(date1, format = '%B %d %Y, %I:%M%p '),
date1_utc = date1_orig + hours(offset_date1),
date2_orig = as_datetime(date2, format = '%Y-%m-%d %H:%M:%S'),
date2_utc = date2_orig + hours(offset_date2),
) %>%
{. ->> my_dates_utc}
my_dates_utc
# # A tibble: 2 x 10
# date1 date2 date1_tz date2_tz offset_date1 offset_date2 date1_orig date1_utc date2_orig date2_utc
# <chr> <chr> <chr> <chr> <dbl> <dbl> <dttm> <dttm> <dttm> <dttm>
# February 11 2017, 6:05am PST 2013-12-14 00:58:00 CET PST CET -8 1 2017-02-11 06:05:00 2017-02-10 22:05:00 2013-12-14 00:58:00 2013-12-14 01:58:00
# April 24 2018, 4:09pm PDT 2013-06-19 18:00:00 CEST PDT CEST -7 2 2018-04-24 16:09:00 2018-04-24 09:09:00 2013-06-19 18:00:00 2013-06-19 20:00:00
现在我们有两组日期时间格式的日期,并且在同一时区,我们可以计算它们之间的时差。
# now calculate difference between them
my_dates_utc %>%
select(date1_utc, date2_utc) %>%
mutate(
difference_days = interval(start = date1_utc, end = date2_utc) %>% time_length(unit = 'days')
)
# # A tibble: 2 x 3
# date1_utc date2_utc difference_days
# <dttm> <dttm> <dbl>
# 2017-02-10 22:05:00 2013-12-14 01:58:00 -1155.
# 2018-04-24 09:09:00 2013-06-19 20:00:00 -1770.
这对于小规模的操作应该没问题。如果您有超过 2 个不同的日期时间格式向量,则值得考虑更复杂的操作,将数据从宽格式转换为长格式。这将避免为每一列重复 same/similar 代码,就像我们在本例中为 date1
和 date2
所做的那样。
我需要一些有关不同时区润滑功能的帮助。我有两个这样的向量:
date1 = c("February 11th 2017, 6:05am PST", "April 24th 2018, 4:09pm PDT")
date2 = c("2013-12-14 00:58:00 CET", "2013-06-19 18:00:00 CEST")
我想使用 lubridate 函数(我试过 mdy_hm)将这些字符串转换为日期格式,然后在考虑时间差异的同时计算两个字符串的差异(以天为单位)时区,其中 PDT 中的 D 代表夏令时,PST 中的 S 代表太平洋时间的标准时区 (https://www.timeanddate.com/time/zones/pdt and https://www.timeanddate.com/time/zones/pst) and similarly for CET (https://time.is/CET) and CEST (https://time.is/CEST)。你能帮帮我吗?
我做的第一件事是用你的 2 个日期向量设置一个 tibble
tibble(
date1 = c("February 11th 2017, 6:05am PST", "April 24th 2018, 4:09pm PDT"),
date2 = c("2013-12-14 00:58:00 CET", "2013-06-19 18:00:00 CEST"),
) %>%
{. ->> my_dates}
my_dates
# # A tibble: 2 x 2
# date1 date2
# <chr> <chr>
# February 11th 2017, 6:05am PST 2013-12-14 00:58:00 CET
# April 24th 2018, 4:09pm PDT 2013-06-19 18:00:00 CEST
然后,列出时区缩写及其与 UTC 的偏移量
# setup timezones and UTC offsets
tribble(
~tz, ~offset,
'PST', -8,
'PDT', -7,
'CET', +1,
'CEST', +2
) %>%
{. ->> my_tz}
my_tz
# # A tibble: 4 x 2
# tz offset
# <chr> <dbl>
# PST -8
# PDT -7
# CET 1
# CEST 2
然后,我们通过删除 date1
中天数后面的字符后缀('11th' 之后的 'th' 位)来整理日期时间。我们还提取时区代码并将其放在单独的列中;时区列允许我们 left_join()
my_tz
,给我们 UTC 偏移量。
我们使用 stringr
package, and regex expressions to find, extract and replace the components. A very handy tool for testing regex patterns can be found here https://regex101.com/r/5pr3LL/1/
my_dates %>%
mutate(
# remove the character suffix after the day number (eg 11th)
day_suffix = str_extract(date1, '[0-9]+[a-z]+') %>% str_extract('[a-z]+'),
date1 = str_replace(date1, day_suffix, ''),
day_suffix = NULL,
# extract timezone info
date1_tz = str_extract(date1, '[a-zA-Z]+$'),
date2_tz = str_extract(date2, '[a-zA-Z]+$'),
) %>%
# join in timezones for date1
left_join(my_tz, by = c('date1_tz' = 'tz')) %>%
rename(
offset_date1 = offset
) %>%
# join in timezones for date2
left_join(my_tz, by = c('date2_tz' = 'tz')) %>%
rename(
offset_date2 = offset
) %>%
{. ->> my_dates_info}
my_dates_info
# # A tibble: 2 x 6
# date1 date2 date1_tz date2_tz offset_date1 offset_date2
# <chr> <chr> <chr> <chr> <dbl> <dbl>
# February 11 2017, 6:05am PST 2013-12-14 00:58:00 CET PST CET -8 1
# April 24 2018, 4:09pm PDT 2013-06-19 18:00:00 CEST PDT CEST -7 2
所以现在,我们可以使用lubridate::as_datetime()
将date1
和date2
转换为dttm
(日期时间)格式。 as_datetime()
采用字符格式的日期时间并将其转换为日期时间格式。您必须使用符号和缩写说明 here 指定字符串的格式。例如,这里我们使用%B
来表示月份的全称,%d
是天数,%Y
是(4位)年数等等。
注意:因为我们没有在 as_datetime()
内指定时区,所以与这些日期时间一起存储的基础时区默认为 UTC
(如使用 tz()
所示)。这就是我们将这些列称为 date*_orig
的原因,以提醒我们时区是原始日期时间的时区。然后我们将偏移量添加到 datetime 对象,所以我们现在有这些 UTC 时间(这些值的基础时区签名是 UTC
,所以这是理想的)。
# now define datetimes in local and UTC timezones (note: technically the tz is UTC for both)
my_dates_info %>%
mutate(
date1_orig = as_datetime(date1, format = '%B %d %Y, %I:%M%p '),
date1_utc = date1_orig + hours(offset_date1),
date2_orig = as_datetime(date2, format = '%Y-%m-%d %H:%M:%S'),
date2_utc = date2_orig + hours(offset_date2),
) %>%
{. ->> my_dates_utc}
my_dates_utc
# # A tibble: 2 x 10
# date1 date2 date1_tz date2_tz offset_date1 offset_date2 date1_orig date1_utc date2_orig date2_utc
# <chr> <chr> <chr> <chr> <dbl> <dbl> <dttm> <dttm> <dttm> <dttm>
# February 11 2017, 6:05am PST 2013-12-14 00:58:00 CET PST CET -8 1 2017-02-11 06:05:00 2017-02-10 22:05:00 2013-12-14 00:58:00 2013-12-14 01:58:00
# April 24 2018, 4:09pm PDT 2013-06-19 18:00:00 CEST PDT CEST -7 2 2018-04-24 16:09:00 2018-04-24 09:09:00 2013-06-19 18:00:00 2013-06-19 20:00:00
现在我们有两组日期时间格式的日期,并且在同一时区,我们可以计算它们之间的时差。
# now calculate difference between them
my_dates_utc %>%
select(date1_utc, date2_utc) %>%
mutate(
difference_days = interval(start = date1_utc, end = date2_utc) %>% time_length(unit = 'days')
)
# # A tibble: 2 x 3
# date1_utc date2_utc difference_days
# <dttm> <dttm> <dbl>
# 2017-02-10 22:05:00 2013-12-14 01:58:00 -1155.
# 2018-04-24 09:09:00 2013-06-19 20:00:00 -1770.
这对于小规模的操作应该没问题。如果您有超过 2 个不同的日期时间格式向量,则值得考虑更复杂的操作,将数据从宽格式转换为长格式。这将避免为每一列重复 same/similar 代码,就像我们在本例中为 date1
和 date2
所做的那样。