r - 通过 Lubridate 转换日期中的字符串,月、日、年、小时、分钟、上午/下午和时区的变化
问题描述
我需要一些关于不同时区的润滑功能的帮助。我有两个这样的向量:
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 中的 Light 和 S 代表太平洋时间的标准时区(https://www.timeanddate.com/time/zones/pdt和https://www.timeanddate.com/time/zones/pst),同样代表 CET ( https://time.is/CET ) 和 CEST ( https://time.is/CEST )。请你帮助我好吗?
解决方案
我做的第一件事是用你的 2 个日期向量设置一个小标题
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”位)来整理日期时间。我们还提取了时区代码并将其放在单独的列中;timezone 列允许我们进入left_join()
my_tz
,给我们 UTC 偏移量。
我们使用stringr
包中的字符串处理函数和正则表达式来查找、提取和替换组件。可以在这里找到一个非常方便的测试正则表达式模式的工具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()
todate1
和date2
to dttm
(datetime) 格式进行转换。as_datetime()
采用字符格式的日期时间并将其转换为日期时间格式。您必须使用此处说明的符号和缩写指定字符串的格式。例如,这里我们%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 个不同的日期时间格式向量,则值得考虑更复杂的操作,将数据从宽格式转换为长格式。这将节省为每一列重复相同/相似的代码,就像我们在这个例子中所做的那样date1
。date2
推荐阅读
- hive - 在 HIVE 中将字符列转换为数字
- matrix - 如何在 STATA 中创建矩阵
- elasticsearch - ElasticSearch 返回一个字段中出现超过 5 个术语的文档
- python - 如何使用提取从熊猫数据框中提取大写字母和一些子字符串?
- swift - 我们如何在 SwiftUI 中使用 GeometryReader 获取和读取文本的大小?
- uml - 在类图中显示列表中的选择
- mysql - 将特定的 WooCommerce 行项目与另一个进行计数
- javascript - ng2-chart lib 没有导出成员,例如:ChartDataSetBase 等
- java - 带有 https 的 Azure 应用服务
- azure - 如何在 Azure 服务总线中管理主题和事件/消息的发布?