基本概念
时间概念
UTC:(英文“Coordinated Universal Time”/法文“Temps Universel Coordonné”),协调世界时,又称世界标准时间或世界协调时间
- 最主要的世界时间标准,其以 [原子时] 秒长为基础,在时刻上尽量接近于格林尼治标准时间。
- 协调世界时把时间分为天、小时、分钟和秒
格林威治标准时间;英语:Greenwich Mean Time,GMT)是指位于英国伦敦郊区的皇家格林尼治天文台当地的标准时间,因为本初子午线被定义为通过那里的经线。
- 理论上来说,格林尼治标准时间的正午是指当太阳横穿格林尼治子午线时(也就是在格林尼治上空最高点时)的时间。但由于地球在它的椭圆轨道里的运动速度不均匀,这个时刻可能与实际的太阳时有误差,最大误差达16分钟。原因在于地球每天的自转是有些不规则的,而且正在缓慢减速,因此格林尼治时间基于天文观测本身的缺陷,已经不再被作为标准时间使用。
- 现在的标准时间,是由 [原子钟] 报时的协调世界时(UTC)来决定。
R语言中的时间
R语言的基础包中提供了两种类型的时间数据
- Date类型,仅包括日期数据,它不包括时间和时区信息
- POSIXct / POSIXlt 类型,其中包括了日期、时间和时区信息。
日期-时间=不可运算
默认情况下,日期是以
/
或者-
进行分隔,而时间则以:
进行分隔;
POSIXct / POSIXlt / strptime 的区别
- POSXIct :它存储自UNIX纪元(+其他数据)以来的秒数 ;用数字表示,一个较大的整数,可以存储到数据框中
- POSIXlt :日期时间类,精确到秒,用列表表示,可以更精确地存储日/月/年/小时/分钟/秒等
函数运行 - POSIXlt
- strptime :字符向量(各种格式)直接转换为POSIXlt格式的函数
- as.POSIXlt:将各种数据类型转换为POSIXlt。
函数运行 - POSIXct
- as.POSIXct:将各种数据类型转换为POSIXct。
- 它首先运行
strptime
,然后从POSIXlt
到POSIXct
的转换
- 它首先运行
- parse_date_time:将各种类型的数据转为为POSIXct
lubridate包主要有两类函数:
- 处理时点数据(time instants)
- 处理时段数据(time spans)
时点类
解析与提取日期 - Prasing
解析日期,
year(x)
设定日期,通过赋值进行设定
year(x) <- value
解析日期 + 排列
- ymd("...", tz=NULL) / dmy() / mdy() :处理不同顺序的日期数据,使之按年月日的形式排列
- dym() / ydm()
tz = NULL; 或为 指定的时区
locale = Sys.getlocale("LC_TIME") :默认;
# 处理日期,使之按年月日的形式排列
> mdy("06-04-2011")
[1] "2011-06-04"
> dmy("04/06/2011")
[1] "2011-06-04"
ymd('20170208')
[1] "2017-02-08"
- hms("...", roll=FALSE) / hm() / ms() :处理不同顺序的时间数据
roll=FALSE 默认;若为TRUE,则根据规则进行换算
# 处理时间
> hms("14:20:01")
[1] "14H 20M 1S"
> hms("01:59:120")
[1] "1H 59M 120S"
> hms("01:59:120",roll=T) # roll=T,进行换算
[1] "2H 1M 0S"
ymd_hms("20161120220000")
[1] "2016-11-20 22:00:00 UTC"
- ymd_hms("...", tz="UTC", locale=Sys.getlocale("LC_TIME"), truncated = 0) / ymd_hm / ymd_h :处理不同顺序的日期时间数据
- dmy_hms /dmy_hm /dmy_h
- mdy_hms / mdy_hm / mdy_h
... : 一个字符串向量 in year, month, day, hour, minute, second format
tz ="UTC" :世界标准时间
提取日期
- year("") / month() / week() / day() / hour() / minute() / second() :解析日期中的部分值
- month(x, label=FALSE, abbr=TRUE)
label= FALSE,默认;将月份作为数值进行显示;若为TRUE,则作为字符串 "January."
abbr = TRUE,默认,将月份作为字符串的缩写进行显示"Jan",当label为FALSE时忽略该参数;若为FALSE,则显示全称 "January."; (abbreviate :缩写)
- yday(x):一年中的第几天
- mday(x):一个月中的第几天
- wday(x):一周中的星期几 [1, 7]
- qday(x):一个季度中的第几天
- days_in_month() :返回所属月份的最大天数
- am(x) / pm(x) :返回逻辑值,判断是否为上午/下午
- 12:00:00 判断为下午;
am(hms('11:59:59')) [1] TRUE am(hms('12:00:00')) [1] FALSE
- 12:00:00 判断为下午;
> year('2017-01-02')
[1] 2017
> month('2017-01-02')
[1] 1
> month('2017-01-02', label=T)
[1] Jan
## 设定日期-----------------------------
> x <- ymd('2010-04-08'); x
[1] "2010-04-08"
> month(x) <- 5 ; x
[1] "2010-05-08"
> days_in_month(as.Date('2017-05-10'))
May
31
转换
parse_date_time 将格式各样的日期时间字符串转换为日期时间类型的数据,并通过orders指定显示的顺序
- parse_date_time(x, orders, tz = "UTC", truncated = 0, quiet = FALSE, locale = Sys.getlocale("LC_TIME"), select_formats = .select_formats, exact = FALSE):将向量转换为POSIXct的日期时间格式
- 与strftime的两点区别:
- 指定一个特殊的排列顺序,而无需使用
%
- 在处理复合的日期时间数据时,可同时指定多个排列顺序
- 指定一个特殊的排列顺序,而无需使用
- 与strftime的两点区别:
x :一个字符串 或数值 向量
order =c(""): 指定的日期显示顺序 ; 若涉及到日期与时间,将时间的小写改为大写; eg
ymd_HMS
tz ="UTC" :世界标准市价
> x <- c("09-01-01", "09-01-02", "09-01-03")
> parse_date_time(x, "ymd")
[1] "2009-01-01 UTC" "2009-01-02 UTC" "2009-01-03 UTC"
## 复合时间
# 处理复合的日期时间数据时,可同时指定多个排列顺序
x <- c("09-01-01", "090102", "09-01 03", "09-01-03 12:02")
parse_date_time(x, c("ymd", "ymd_HM"))
## 不同的排序规则 - 可以同时处理
> x <- c("2009-01-01", "02022010", "02-02-2010")
> parse_date_time(x, c("dmY", "ymd"))
[1] "2009-01-01 UTC" "2010-02-02 UTC" "2010-02-02 UTC"
## 季度与部分日期
> parse_date_time(c("2016.2", "2016-04"), orders = "Yq") # q 代表季度;
[1] "2016-04-01 UTC" "2016-10-01 UTC"
> parse_date_time(c("2016", "2016-04"), orders = c("Y", "Ym"))
[1] "2016-01-01 UTC" "2016-04-01 UTC"
# Y 与 y 的区别 # Y大写表示全称;y表示缩写;
> parse_date_time(c("16.2", "16-04"), orders = "yq")
[1] "2016-04-01 UTC" "2016-10-01 UTC"
> parse_date_time(c("16.2", "16-04"), orders = "Yq")
[1] NA NA
- decimal_date(x):将日期格式转化为小数格式;
x : a POSIXlt/ct or Date object
- date_decimal(x) :将小数转化为日期格式
date <- ymd("2009-02-10")
decimal_date(date)
[1] 2009.11
date_decimal(decimal_date(date))
[1] "2009-02-10 UTC"
- as.Date():以数值形式存储,精确到天
- 解析类函数,默认已完成了格式转换;eg
ymd("2012-04-21")
- 解析类函数,默认已完成了格式转换;eg
- as.POSIXct() :以一个数值形式进行存储,精确到秒
- as.POSIXlt() :以列表的形式进行存储,精确到秒
- unclass(x) :
- 可以将日期变成以天来计数 ;
- 可以将时点类根据最基本的组成进行拆解
x<-as.Date("1970-01-01")
> unclass(x)
[1] 0
>
> unclass(as.Date("1970-02-01")) #19700201代表第31天
[1] 31
# --------对时点类时间进行拆解--------------------------------------
## POSIXct 格式;主要特点:以秒进行存储。
> unclass(now()) # 等价于 unclass(as.POSIXct(now()))
[1] 1501495056
attr(,"tzone")
[1] ""
## POSIXlt 格式;主要特点:以列表进行单独储存格式,可以作为时间筛选的一种
> unclass(as.POSIXlt(now()))
$sec
[1] 18.43142
$min
[1] 58
$hour
[1] 17
$mday
[1] 31
$mon
[1] 6
$year
[1] 117
$wday
[1] 1
$yday
[1] 211
$isdst
[1] 0
$zone
[1] "CST"
$gmtoff
[1] 28800
attr(,"tzone")
[1] "" "CST" "CDT"
起始日期为1970-01-01
获取
- today( [tz=""]):返回当前系统的日期,不含时间;时区默认为当前计算机的时区
- now( [tz=""]):作为POSIXct对象返回当前系统的日期与时间 ;时区默认为当前计算机的时区
> today()
[1] "2017-07-31"
> now()
[1] "2017-07-31 15:43:46 CST"
舍入 - Rounding
- round_date(x, unit = "second") :根据unit对x进行四舍五入;
unit ="" :可选的单位
- second(s) / mintue(s) / hour(s) / day(s)
- week(s) / month(s) / quarter()
- haflyear / year
- floor_date(x, unit = "second"):向下舍入;
- 相当于取整;若unit="hour" ,则舍去分钟的内容
- ceiling_date(x, unit = "second", change_on_boundary = NULL):向上舍入;
- 向上取整; 若后面一位小数大于0,即向前进一位
函数实际运行的三个步骤
- 转换为表示日期下限的时点:2000-01-01 –> 2000-01-01 00:00:00
- 向上舍入到下一个最接近的单位边界。 if the rounding unit is month then next boundary for 2000-01-01 will be 2000-02-01 00:00:00.
- 如果舍入的最小边界单位小于一天,则返回第二步的时点
## round_date--------------------------------------------------
x <- as.POSIXct("2009-08-03 12:01:59.23"); x
[1] "2009-08-03 12:01:59 CST"
round_date(x, "minute") # 舍入到分钟
[1] "2009-08-03 12:02:00 CST"
> round_date(x, "5 minute")
[1] "2009-08-03 12:00:00 CST"
> round_date(x, "2 months")
[1] "2009-09-01 CST"
round_date(x, "quarter") == round_date(x, "3 months")
round_date(x, "halfyear")
round_date(x, "year")
## floor_date--------------------------------------------------
x <- as.POSIXct("2009-08-03 12:01:59.23")
> floor_date(x, "hour")
[1] "2009-08-03 12:00:00 CST"
## ceiling_date------------------------------------------------
x <- as.POSIXct("2009-08-03 12:01:59.23")
> ceiling_date(x, "second")
[1] "2009-08-03 12:02:00 CST"
设定时点
设定时点的两种方法:
- 通过解析函数设定
- 通过时段类函数设定
- 通过解析函数设定
#解析日期
year(x)
#设定日期,通过赋值进行设定
year(x) <- value
> l <- today(); l
[1] "2017-07-31"
> day(l) <- 10; l
[1] "2017-07-10"
# 不可直接对today()进行赋值
day(today())<- 10 # 显示报错
- 通过时段类函数直接设定
## 通过period来设定时间,一般为unit之后加s; 例如days / months
> today() + days(1)
[1] "2017-08-01"
## 通过 duraction来设定时间,一般period之前加d;即对原始先加s,在加d; 例如 ddays / dyears
> today() + ddays(1)
[1] "2017-08-01"
时段类
间隔 - Intervals
interval:最简单的时段对象,它由两个时点数据构成。
- 间隔类型:
is.intervals
&as.intervals
- interval(start, end, tzone = attr(start, "tzone")):创建时间间隔
## 创建时间间隔
> x <- ymd('2010-04-08')
> interval(x,now())
[1] 2010-04-08 08:00:00 CST--2017-07-31 16:41:43 CST
int_length() :间隔的长度,以秒来计算
int_start() / int_end() :返回间隔的起始/结束日期时间
int_shift(int, by):对间隔两端同时进行转换
by = duration( ): 一段持续时间或周期
## 转换
int <- interval(ymd("2001-01-01"), ymd("2002-01-01"))
int_shift(int, duration(days = 11))
[1] 2001-01-12 UTC--2002-01-12 UTC
int_shift(int, duration(hours = -1))
[1] 2000-12-31 23:00:00 UTC--2001-12-31 23:00:00 UTC
- int_flip(int):翻转;将interval的起始时间与结束时间对调
- int_standardize():标准化;确保间隔是正值,即结束时间大于开始时间;若非标准化,则自动调整
int <- interval(ymd("2001-01-01"), ymd("2002-01-01"))
int_flip(int)
[1] 2002-01-01 UTC--2001-01-01 UTC
int_standardize(int_flip(int))
[1] 2001-01-01 UTC--2002-01-01 UTC
- int_diff(times):时间间隔对象, 包含 n-1段的时间间隔
times为POSIXct, POSIXlt 或日期格式
> dates <- now() + days(1:4); dates
[1] "2017-08-01 17:00:07 CST" "2017-08-02 17:00:07 CST" "2017-08-03 17:00:07 CST" "2017-08-04 17:00:07 CST"
> int_diff(dates)
[1] 2017-08-01 17:00:07 CST--2017-08-02 17:00:07 CST 2017-08-02 17:00:07 CST--2017-08-03 17:00:07 CST
[3] 2017-08-03 17:00:07 CST--2017-08-04 17:00:07 CST
int_overlaps(int1, int2):判断int1与int2之间是否有重叠的部分;并返回逻辑值 T/F
int_aligns(int1, int2):判断int1与int2是否对齐,并返回逻辑值 T / F
aligns : 对齐
若int1与int2 有相同的起始时间或结束时间,则返回T; 否则返回FALSE
int1 <- interval(ymd("2001-01-01"), ymd("2002-01-01"))
int2 <- interval(ymd("2001-06-01"), ymd("2002-01-01"))
int3 <- interval(ymd("2003-01-01"), ymd("2004-01-01"))
int_aligns(int1, int2) # TRUE ## 有相同的结束时间
int_aligns(int1, int3) # FALSE
## 判断是否有重叠
int_overlaps(int1, int2) # TRUE
int_overlaps(int1, int3) # FALSE
- time_length(x, unit = "second") :计算两个时间之间的间隔 (自定义间隔单位)
x :a duration, period, difftime or interval
unit = c("second", "minute", "hour","day", "week","month", "year"))
- difftime(time1, time2, tz,units=c("") ) :计算两个时间之间的间隔 (自定义间隔单位)
- 该函数为Base函数
units = c("auto", "secs", "mins", "hours","days", "weeks"))
%within%
持续时间 - Durations
- duration:去除了时间两端的信息,纯粹以秒为单位计算时段的长度,不考虑闰年和闰秒,它同时也兼容基本包中的difftime类型对象。
- 期间类型 :
is.duration(x)
&as.duration
- duration(num = NULL, units = "seconds", ...):创建持续时间
duration(90, "seconds")
duration(1.5, "minutes")
## 比较判断
duration("day 2 sec") > "day 1sec"
is.duration(as.Date("2009-08-03")) # FALSE
is.duration(duration(days = 12.4)) # TRUE
- dyears(x) / dweeks(x) / ddays(x) /dhours(x) / dminutes(x) / dseconds(x) :快速创建持续时间的对象以便于进行日期时间操作
- 没有dmonths(),因为其以秒为单位来创建,而月度常在30天/31天之间变化;而年度的话此时默认为365天;
Durations的函数,以 [秒] 为单位进行创建
- minutes(2)函数表示的2个整分钟的概念,而dminutes(2)则是具体120秒
- years(1)则是一个整年的概念而dyears(1)表示的365天**而
## 规则说明:以 [秒] 为单位进行创建
> dyears(1)
[1] "31536000s (~52.14 weeks)"
> years(1)
[1] "1y 0m 0d 0H 0M 0S"
## 具体区别
> ymd('20160228')+dyears(1) # 以秒为单位进行扩展
[1] "2017-02-27"
> ymd('20160228')+years(1) # 以年为单位进行扩展
[1] "2017-02-28"
周期 - Periods
period:以较长的时钟周期来计算时段长度,它考虑了闰年和闰秒,适用于长期的时间计算。
- 周期类型:
is.period
&as.period
- period(num = NULL, units = "second", ...):创建周期
> period(-1, "days")
[1] "-1d 0H 0M 0S"
> period(c(3, 1, 2, 13, 1), c("second", "minute", "hour", "day", "week"))
[1] "20d 2H 1M 3S"
- years(x) / months(x) / weeks(x) / days(x) / hours(x) / minutes() / seconds(x):快速创建阶段对象以便于进行日期时间操作
Durations的函数,以 [创建的函数单位] 为单位进行创建
- minutes(2)函数表示的2个整分钟的概念,而dminutes(2)则是具体120秒
- years(1)则是一个整年的概念而dyears(1)表示的365天而
# 规则说明:以[创建的函数单位]为单位进行创建
> dyears(1)
[1] "31536000s (~52.14 weeks)"
> years(1)
[1] "1y 0m 0d 0H 0M 0S"
# 具体应用
> x <- as.POSIXct("2009-08-03");x
[1] "2009-08-03 CST"
> x + days(1) + hours(6) + minutes(30)
[1] "2009-08-04 06:30:00 CST"
时区 - Time Zones
时区索引
- tz(x):提取时间数据的时区
- with_tz(time, tz=""):将时间数据[显示] 为另一个时区的同一时间
- force_tz(timez, tz=""):将时间数据的时区[强制转换] 为另一个时区
tz(x) <- value # 设置时区
> meeting <- ymd_hms("2011-07-01 09:00:00", tz = "Pacific/Auckland");meeting
[1] "2011-07-01 09:00:00 NZST"
> with_tz(meeting, "America/Chicago") #显示不同的时区相同的时刻
[1] "2011-06-30 16:00:00 CDT"
> mistake <- force_tz(meeting, "America/Chicago");mistake # 强制转化为另一个时区
[1] "2011-07-01 09:00:00 CDT"
> with_tz(mistake, "Pacific/Auckland") # 显示转化之后的另一个时间的同一时间,判断是否转换成功
[1] "2011-07-02 02:00:00 NZST"
混杂的 - Miscellaneous
- leap_years(x) : 判断是否为闰年
- pretty_dates() : provides a method of making pretty breaks for date-times
- make_difftime(num = NULL, units = "auto") :
make_difftime(3600, units = "minute")
# Time difference of 60 mins
make_difftime(second = 3, minute = 1.5, hour = 2, day = 6, week = 1)
# Time difference of 13.08441 days
- %m+% :由于每个月的最后天数不一样,如果直接在某个月份的最后一天加上指定的月数就会出现错误,这时就得考虑使用%m+%函数了。
x <- as.Date('2015-01-31')
y <- x + months(0:11); y
[1] "2015-01-31" NA "2015-03-31" NA "2015-05-31" NA "2015-07-31" "2015-08-31"
[9] NA "2015-10-31" NA "2015-12-31"
> x %m+% months(0:11)
[1] "2015-01-31" "2015-02-28" "2015-03-31" "2015-04-30" "2015-05-31" "2015-06-30" "2015-07-31" "2015-08-31"
[9] "2015-09-30" "2015-10-31" "2015-11-30" "2015-12-31"