R_日期处理_lubridate

基本概念

时间概念

UTC:(英文“Coordinated Universal Time”/法文“Temps Universel Coordonné”),协调世界时,又称世界标准时间世界协调时间

  • 最主要的世界时间标准,其以 [原子时] 秒长为基础,在时刻上尽量接近于格林尼治标准时间
  • 协调世界时把时间分为天、小时、分钟和秒

格林威治标准时间;英语:Greenwich Mean Time,GMT)是指位于英国伦敦郊区的皇家格林尼治天文台当地的标准时间,因为本初子午线被定义为通过那里的经线。

  • 理论上来说,格林尼治标准时间的正午是指当太阳横穿格林尼治子午线时(也就是在格林尼治上空最高点时)的时间。但由于地球在它的椭圆轨道里的运动速度不均匀,这个时刻可能与实际的太阳时有误差,最大误差达16分钟。原因在于地球每天的自转是有些不规则的,而且正在缓慢减速,因此格林尼治时间基于天文观测本身的缺陷,已经不再被作为标准时间使用。
  • 现在的标准时间,是由 [原子钟] 报时的协调世界时(UTC)来决定。


R语言中的时间

R语言的基础包中提供了两种类型的时间数据

  1. Date类型,仅包括日期数据,它不包括时间和时区信息
  2. POSIXct / POSIXlt 类型,其中包括了日期、时间和时区信息。

日期-时间=不可运算

默认情况下,日期是以/或者-进行分隔,而时间则以:进行分隔;


POSIXct / POSIXlt / strptime 的区别

  • POSXIct :它存储自UNIX纪元(+其他数据)以来的秒数 ;用数字表示,一个较大的整数,可以存储到数据框中
  • POSIXlt :日期时间类,精确到秒,用列表表示,可以更精确地存储日/月/年/小时/分钟/秒等

函数运行 - POSIXlt

  • strptime :字符向量(各种格式)直接转换为POSIXlt格式的函数
  • as.POSIXlt:将各种数据类型转换为POSIXlt

函数运行 - POSIXct

  • as.POSIXct:将各种数据类型转换为POSIXct
    • 它首先运行strptime,然后从POSIXltPOSIXct的转换
  • parse_date_time:将各种类型的数据转为为POSIXct


lubridate包主要有两类函数:

  1. 处理时点数据(time instants)
  2. 处理时段数据(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
> 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的两点区别:
      1. 指定一个特殊的排列顺序,而无需使用 %
      2. 在处理复合的日期时间数据时,可同时指定多个排列顺序

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")
  • 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,即向前进一位

函数实际运行的三个步骤

  1. 转换为表示日期下限的时点:2000-01-01 –> 2000-01-01 00:00:00
  2. 向上舍入到下一个最接近的单位边界。 if the rounding unit is month then next boundary for 2000-01-01 will be 2000-02-01 00:00:00.
  3. 如果舍入的最小边界单位小于一天,则返回第二步的时点
## 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"


设定时点

设定时点的两种方法:

  1. 通过解析函数设定
  2. 通过时段类函数设定
  • 通过解析函数设定
#解析日期
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"

你可能感兴趣的:(R_日期处理_lubridate)