R语言时间处理函数

1 POSIXct和POSIXlt


把表示时间的字符串转成时间类型数据,在R语言里面有两个基本的函数:as.POSIXlt() 和 as.POSIXct()。两者都是S3泛型函数,根据参数的数据类型选择不同的转换方法,除字符串外还能够转换数字、因子等数据类型,适应性很强:

as.POSIXlt("2010/01/01")
## [1] "2010-01-01 CST"
as.POSIXlt("2010/01/01 10:30:30")
## [1] "2010-01-01 10:30:30 CST"
as.POSIXlt("10:30:30 2010/01/01", format = "%H:%M:%S %Y/%m/%d")
## [1] "2010-01-01 10:30:30 CST"
tt <- Sys.time()
as.POSIXlt(3600 * 24 * 1001, origin = tt)
## [1] "2019-07-20 07:15:10 CST"
as.POSIXlt(3600 * 24 * 1001, origin = tt, tz = "UTC")
## [1] "2019-07-19 23:15:10 UTC"
as.POSIXct("2010/01/01")
## [1] "2010-01-01 CST"
as.POSIXct("2010/01/01 10:30:30")
## [1] "2010-01-01 10:30:30 CST"
as.POSIXct("10:30:30 2010/01/01", format = "%H:%M:%S %Y/%m/%d")
## [1] "2010-01-01 10:30:30 CST"
as.POSIXct(3600 * 24 * 1001, origin = tt)
## [1] "2019-07-20 07:15:10 CST"
as.POSIXct(3600 * 24 * 1001, origin = tt, tz = "UTC")
## [1] "2019-07-19 23:15:10 UTC"


非标准顺序日期时间字符串需要使用format参数。

那么,什么是POSIXct和POSIXlt?它们间有什么差别?我们需要了解它们的定义:POSIXct用某个时间到UNIX元年(1970-01-01 00:00:00)所经过的秒数来记录时间,即通过计数的方式表示时间(count time);而POSIXlt用列表方式表示时间(list time),时间的每一部分都是列表的一个元素:

(ct <- as.POSIXct("1980-09-30 10:11:12"))
## [1] "1980-09-30 10:11:12 CST"
(lt <- as.POSIXlt("1980-09-30 10:11:12"))
## [1] "1980-09-30 10:11:12 CST"
unlist(ct)
## [1] "1980-09-30 10:11:12 CST"
unlist(lt)
##    sec    min   hour   mday    mon   year   wday   yday  isdst   zone 
##   "12"   "11"   "10"   "30"    "8"   "80"    "2"  "273"    "0"  "CST" 
## gmtoff 
##     NA


lt时间的年份是从1900年开始计数的。在没有任何辅助工具函数的条件下,从一个lt时间中很容易获得年月日时分秒和星期等数据,而ct时间不行:

c(1900 + lt$year, lt$mon, lt$mday, lt$hour, lt$min, lt$sec)
## [1] 1980    8   30   10   11   12


但另一方面,ct时间的存储只需要用一个双精度数,lt则需要一个长列表,相比之下当然是ct节省资源。

虽然最终可能表示相同的时间,但ct时间和lt时间类型数据不是随便可以合并的:

c(ct, lt)
##                                                 sec 
## "1980-09-30 10:11:12 CST" "1970-01-01 08:00:12 CST" 
##                       min                      hour 
## "1970-01-01 08:00:11 CST" "1970-01-01 08:00:10 CST" 
##                      mday                       mon 
## "1970-01-01 08:00:30 CST" "1970-01-01 08:00:08 CST" 
##                      year                      wday 
## "1970-01-01 08:01:20 CST" "1970-01-01 08:00:02 CST" 
##                      yday                     isdst 
## "1970-01-01 08:04:33 CST" "1970-01-01 08:00:00 CST" 
##                      zone                    gmtoff 
##                        NA                        NA
c(lt, ct)
## [1] "1980-09-30 10:11:12 CST" "1980-09-30 10:11:12 CST"
c(NULL, ct)
## [1] 339127872
c(NULL, lt)
## $sec
## [1] 12
## 
## $min
## [1] 11
## 
## $hour
## [1] 10
## 
## $mday
## [1] 30
## 
## $mon
## [1] 8
## 
## $year
## [1] 80
## 
## $wday
## [1] 2
## 
## $yday
## [1] 273
## 
## $isdst
## [1] 0
## 
## $zone
## [1] "CST"
## 
## $gmtoff
## [1] NA
c(ct, NULL)
## [1] "1980-09-30 10:11:12 CST"
c(lt, NULL)
## Error in as.POSIXct.default(X[[i]], ...): do not know how to convert 'X[[i]]' to class "POSIXct"


2 时间的算术运算

ct和lt可以混合运算,但只能求差值,得到的是天数。时间和数字的加减运算是把数字当成秒对待,在顺序上也有讲究,具体看例子:

tt1 <- as.POSIXct("2010-11-12 10:20:30")
tt2 <- as.POSIXlt("2010-11-21 10:30:40")
tt1 - tt2
## Time difference of -9.00706 days
tt1 + tt2
## Error in `+.POSIXt`(tt1, tt2): binary '+' is not defined for "POSIXt" objects
tt1 - 10
## [1] "2010-11-12 10:20:20 CST"
tt1 + 10
## [1] "2010-11-12 10:20:40 CST"
tt1 - 10
## [1] "2010-11-12 10:20:20 CST"
10 + tt1
## [1] "2010-11-12 10:20:40 CST"
10 - tt1
## Error in `-.POSIXt`(10, tt1): can only subtract from "POSIXt" objects



3 获取系统时间和日期

常用Sys.time和Sys.Date函数。

(tt <- Sys.time())
## [1] "2016-10-22 07:15:10 CST"
class(tt)
## [1] "POSIXct" "POSIXt"
as.double(tt)
## [1] 1477091711
(dd <- Sys.Date())
## [1] "2016-10-22"
class(dd)
## [1] "Date"
as.double(dd)
## [1] 17096
as.Date(tt)
## [1] "2016-10-21"
as.POSIXct(dd)
## [1] "2016-10-22 08:00:00 CST"
as.POSIXlt(dd)
## [1] "2016-10-22 UTC"


注意Sys.time获得的是ct时间。


4 字符串转换为时间:

除了as.POSIXlt() 和 as.POSIXct()函数外,还有其他一些函数。如果载入了R语言的其他包,会有更多用法。


4.1 as.Date

用法很简单:

as.Date("2010-10-30")
## [1] "2010-10-30"
as.Date("2010/10/30")
## [1] "2010-10-30"
as.Date("20101030")
## Error in charToDate(x): character string is not in a standard unambiguous format
as.Date("20101030", format = "%Y%m%d")
## [1] "2010-10-30"


format参数用于识别输入字符串的排列顺序。


4.2 strptime与strftime

这两者名称和参数都很像,但这里面有乌龙。先看参数:

args(strptime)
## function (x, format, tz = "") 
## NULL
args(strftime)
## function (x, format = "", tz = "", usetz = FALSE, ...) 
## NULL
strptime("2010-10-10")
## Error in strptime("2010-10-10"): 缺少参数"format",也没有缺省值
strptime("2010-10-10", format = "%Y-%m-%d")
## [1] "2010-10-10 CST"
strftime("2010-10-10")
## [1] "2010-10-10"
strftime("2010-10-10", usetz = TRUE)
## [1] "2010-10-10 CST"
  • format参数在strptime中为必选,在strftime中为可选
  • strptime强制包含时区,而strftime默认不设置时区。如果strftime设置usetz=TRUE,输出结果就和strptime一样

然而,它们返回值的数据类型是完全不一样的:

str(strptime("2010-10-10", format = "%Y-%m-%d"))
##  POSIXlt[1:1], format: "2010-10-10"
str(strftime("2010-10-10", usetz = TRUE))
##  chr "2010-10-10 CST"


strptime得到的是时间类型数据,strftime得到字符串。查看它们的函数源代码会了解得更清楚:

strptime
## function (x, format, tz = "") 
## {
##     y <- .Internal(strptime(as.character(x), format, tz))
##     names(y$year) <- names(x)
##     y
## }
## <bytecode: 0x272a5f0>
## <environment: namespace:base>
strftime
## function (x, format = "", tz = "", usetz = FALSE, ...) 
## format(as.POSIXlt(x, tz = tz), format = format, usetz = usetz, 
##     ...)
## <bytecode: 0x2dad8b8>
## <environment: namespace:base>


strptime函数使用的是内部C语言函数转换字符串为时间;而strftime本质上是字符串格式化函数,先用as.POSIXlt将字符串转为时间,然后用format函数输出字符串。

再说format参数吧,strftime虽然最终使用了strptime,但format参数并没有传递下去,而是作为format函数的参数,用于格式化输出字符串:

strptime("30-10-2010", format = "%d-%m-%Y")
## [1] "2010-10-30 CST"
strftime("30-10-2010", format = "%d-%m-%Y", tz = "CST", usetz = TRUE)
## [1] "20-10-30 CST"
strptime("2010-10-10", format = "%A")
## [1] NA
strftime("2010-10-10", format = "%A")
## [1] "星期日"


strptime得到的是lt时间。再查看as.POSIXlt对字符串处理的源代码会发现,它其实就是对strptime函数的封装。


5 格式化日期/时间的字符串

通过格式化时间,可以得到表示时间的不同部分,也可以把时间按照需要的方式展示出来。在处理日期时间类型数据上,as.character、strftime和format的用法和结果是一样的:

as.character(Sys.Date(), format = "%A")
## [1] "星期六"
strftime(Sys.Date(), format = "%A")
## [1] "星期六"
format(Sys.Date(), format = "%A")
## [1] "星期六"
format(Sys.Date(), format = "%Y年%m月%d日 %A")
## [1] "2016年10月22日 星期六"


strftime灵活一些,能直接处理代表日期时间的字符串:

strftime("2010-10-10", format = "%A")
## [1] "星期日"
as.character(as.POSIXlt("2010-10-10"), format = "%A")
## [1] "星期日"
format(as.POSIXlt("2010-10-10"), format = "%A")
## [1] "星期日"


不同的格式化字符代码不同的意义,具体可用“?format.POSIXct”查看:

strftime("2010-10-30 01:02:03", format = "%Y")
## [1] "2010"
strftime("2010-10-30 01:02:03", format = "%m")
## [1] "10"
strftime("2010-10-30 01:02:03", format = "%d")
## [1] "30"
strftime("2010-10-30 01:02:03", format = "%H")
## [1] "01"
strftime("2010-10-30 01:02:03", format = "%M")
## [1] "02"
strftime("2010-10-30 01:02:03", format = "%S")
## [1] "03"
strftime("2010-10-30 01:02:03", format = "%A")
## [1] "星期六"
strftime("2010-10-30 01:02:03", format = "%B")
## [1] "十月"
strftime("2010-10-30 01:02:03", format = "%c")
## [1] "2010年10月30日 星期六 01时02分03秒"


字符串的输出与locale有关,可通过LC_TIME设置以获得想要的格式。

xx <- Sys.getlocale("LC_TIME")
Sys.setlocale("LC_TIME", "C")
## [1] "C"
strftime("2010-10-30 01:02:03", format = "%A")
## [1] "Saturday"
strftime("2010-10-30 01:02:03", format = "%B")
## [1] "October"
strftime("2010-10-30 01:02:03", format = "%c")
## [1] "Sat Oct 30 01:02:03 2010"
Sys.setlocale("LC_TIME", xx)
## [1] "zh_CN.utf8"


作者: ZGUANG@LZU

Created: 2016-10-22 六 07:14

Emacs 24.4.1 (Org mode 8.2.10)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值