约万字长文预警,如果你没时间,就不用看了,这就是一个梳理的文章,方便我后来找资料。
因为工作的关系,近期需要梳理一些 Python 的知识(可能有小伙伴知道了,LI-6800 搞了个大动作,支持 Python 编程了),首先要认真系统的梳理的是关于时间和日期的处理,但本着一次也是做工作,两次也是做工作,反正都同样是知识,二者也是密切相关,所幸把 R 相关的知识也一并梳理了。
时间日期的基础知识
先把经常用到的一些时间的概念进行一下整理。因为不用不知道,一用吓一跳,时间的标准、名词、定义还真不少。
Gregorian calendar
格里高里历,这个名字不熟悉,实际上就是标准的公立。
ISO 时间
对于我国人民来讲,ISO 8601 这个标准虽然没怎么听过,但是实际我们一直在用,这就是我国使用的时间日期所采取的格式。年月日和时间的格式我们不再赘述,它可以作为下面项目的标准用法:
•日期•时间•世界调整时间(UTC)•与 UTC 有补偿的当期时间(如夏令时)•时间和日期•时间间隔•循环的时间间隔
UT (世界时)
以下是百度百科内容
世界时UT即格林尼治平太阳时间,是指格林尼治所在地的标准时间,也是表示地球自转速率的一种形式。以地球自转为基础的时间计量系统。地球自转的角度可用地方子午线相对于地球上的基本参考点的运动来度量。为了测量地球自转,人们在地球上选取了两个基本参考点:春分点(见分至点)和平太阳点,由此确定的时间分别称为恒星时和平太阳时。
UTC 时间
UTC 是一个时间标准,以下是百度百科内容
国际原子时的准确度为每日数纳秒,而世界时的准确度为每日数毫秒。许多应用部门要求时间系统接近世界时UT,对于这种情况,一种称为协调世界时的折衷时标于1972年面世。为确保协调世界时与世界时相差不会超过0.9秒,在有需要的情况下会在协调世界时内加上正或负闰秒。因此协调世界时与国际原子时之间会出现若干整数秒的差别,两者之差逐年积累,便采用跳秒(闰秒)的方法使协调时与世界时的时刻相接近,其差不超过1s。它既保持时间尺度的均匀性,又能近似地反映地球自转的变化。中国大陆、中国香港、中国澳门、中国台湾、蒙古国、新加坡、马来西亚、菲律宾、西澳大利亚州的时间与UTC的时差均为+8,也就是UTC+8。
也就是他的确定有两大核心要素:
•International Atomic Time (TAI):简单了讲就是用 400 个高精原子时钟的输出结果,作为我们使用时钟追踪的标准。•Universal Time (UT): 指的是地球自转一周的时间。
unix time
unix 时间又被成为 Epoch 时间,POSIX 时间,特征十分明显,记录自1970年1月1日起已经过多少秒 00:00:00 的协调世界时(UTC),减去闰秒(“闰秒,是指为保持协调世界时接近于世界时时刻,由国际计量局统一规定在年底或年中(也可能在季末)对协调世界时增加或减少1秒的调整。)。
每天被视为完全包含86 400秒,所以从纪元开始减去闰秒。所以我们看到 LI-6800 有一列时间很奇怪,现在看来那没什么好奇怪的,因为距离 1970 年,换算成秒已经很久远了,在手册里也写到了,这是 Epoch time,因为 LI-6800 基于 BSD。
至于为什么会用这么奇怪的时间格式,根本原因就是这玩意对计算机太友好了,不用为了不同的时间格式转换来转换去,匹配了才能计算时间,虽然对人类不太友好。但如果我们知道是 unix 时间,那么很多软件转换它也就是一行代码而已。
夏令时
我直接复制百度百科的内容:
夏令时,表示为了节约能源,人为规定时间的意思。也叫夏时制,夏时令(Daylight Saving Time:DST),又称“日光节约时制”和“夏令时间”,在这一制度实行期间所采用的统一时间称为“夏令时间”。一般在天亮早的夏季人为将时间调快一小时,可以使人早起早睡,减少照明量,以充分利用光照资源,从而节约照明用电。
我觉得这就是自欺欺人的玩意,你想节约能源,让人早睡早起的话,直接下令早起一小时就好了,何必非得折腾时间呢?反正都是早睡早起,哪有这么多切换时间的麻烦,还好我国已经废止了。现在美帝还有这些事,我们应该没机会处理这堆烂事。
GMT 时间
GMT 也就是我们所熟悉的格林威治时间,在 1972 年以前,它是一个时间标准,在那之后,他就仅仅指它所在的地方的时区。所以我们应该几乎不会再处理这种格式的数据了。
时区
这看上去是最好理解的概念,但实际上又不然,一幅图可以展示所有时区:
但我觉得需要注意的有下面几点:
1.当地时间与 UTC 有差异,比如我们常见到的我们这边的时间 UTC+8,因为我们在东八区嘛。2.如果严格的按照经度 15° 来算,应为 24 个时区,但是人类世界从来不会这么简单的遵循科学的规律,我们要考虑政治边界等因素,所以,数量要远高于 24.3.另一个是夏令时,我觉得很虚伪的做法,远不如行政命令,简化时间算法来的直接。4.另一个是所在地区的时间未必与时区相同,这个也是无解的。例如,新疆应该属于东六区,但就是习惯用东八区计时。
CST
CST 是很常见的一个缩写,以下抄袭自百度百科:
CST可以为如下4个不同的时区的缩写:
•美国中部时间:Central Standard Time (USA) UT-6:00•澳大利亚中部时间:Central Standard Time (Australia) UT+9:30•中国标准时间:China Standard Time UT+8:00•古巴标准时间:Cuba Standard Time UT-4:00
我们说的自然是指 UTC+8 的时间。
R 日期与时间
从这里进入正式的处理,这里梳理的目的不是做到面面俱到,只是期望有一个思路,有问题也方便查找。
日期
日期最常用的转换就是文字转换为日期,有几种方法
as.Date
作为 base R 的基本函数,as.Date
的作用就是将字符转换为日期类。对于仪器类的时间日期,它其中非常有用的参数是 format
,但它又牵扯到 strptime
,我们通过例子查看:
# 前三行后面解释lct Sys.getlocale("LC_TIME")Sys.setlocale("LC_TIME", lct)Sys.setlocale("LC_TIME", "C")# 这类仪器的时间日期还能接受x "1jan1960", "2jan1960", "31mar1960", "30jul1960")z as.Date(x, "%d%b%Y")z# 这类仪器的厂家简直就没有国际视野x "02/27/19", "02/27/19", "01/14/19", "02/28/19", "02/01/19")z as.Date(x, "%m/%d/%y")z# 这不管公司大小,至少是有估计视野的# 如果需要日期计算,我们就将字符转换文字就行y "2019-12-31", "2020-1-1", "2020-1-2")y
## [1] "Chinese (Simplified)_China.936"
## [1] "C"
## [1] "1960-01-01" "1960-01-02" "1960-03-31" "1960-07-30"
## [1] "2019-02-27" "2019-02-27" "2019-01-14" "2019-02-28" "2019-02-01"
## [1] "2019-12-31" "2020-1-1" "2020-1-2"
这个代码本身非常简单,除了下面要解释的两点(其实本质上就是 strptime
一点):
•format
参数中这些带 % 号的字符来自于 POSIX
标准,在 R 和 Python内都是一样的符号,即使用 % + 字母,来规定时间与日期的格式,有需要查阅 ?strptime
•在 Sys.setlocale
中使用 "C",以及 "LC_TIME",帮助文档有解释:
Locale-specific conversions to and from character strings are used where appropriate and available. This affects the names of the days and months, the AM/PM indicator (if used) and the separators in output formats such as %x and %X, via the setting of the LC_TIME locale category. The ‘current locale’ of the descriptions might mean the locale in use at the start of the R session or when these functions are first used. (For input, the locale-specific conversions can be changed by calling Sys.setlocale with category LC_TIME (or LC_ALL). For output, what happens depends on the OS but usually works.)
也就是说我们使用格式带有某些字符,如上面的 Jan 等,以及与系统的区域语言设置相关的输出格式,可以通过使用设置 LC_TIME,输出的结果依赖于我们系统的设置。
有点拗口,直接的从结果上来将会比较容易,那就是代码命名没问题,结果输出的结果是 NA,那就要考虑是不是没有按照上面的区域时间日期的设置来更改。这是系统之间和不同地区之间最令人头疼的区域语言设置问题。
另外设置为 C 则是关闭特定区域的顺序,帮助文档里也有:
Sys.setlocale("LC_TIME", "C") # turn off locale-specific sorting, # usually (but not on all platforms)
所有的区域语言设置,目的均是为实现我们上面代码输出的不是 NA,如果不信邪,国内多数人用的电脑应该前两个例子的代码都为 NA。至于标准的 ISO 8601 数据,至少对我们区域语言设置选择中文的 Windows 电脑是非常友好的。
日期的差
在实际应用过程中,时间的差值计算非常多,在 R base 中也有很多方法计算:
例如,你的小学数学没学好,又想学偶像剧搞浪漫,要告诉女友在你们相恋的第 n 天的感受,那么你可以这样做:
Sys.Date() - as.Date("2009-01-18")
## Time difference of 4101 days
更浪漫的精确到 s:
difftime(Sys.time(), strptime("2009-01-18 15:20:22", "%Y-%m-%d %H:%M:%S"), units = "secs")
## Time difference of 354312449 secs
当然,第二条要求你要有惊人的记忆力,或者一个好笔头,如果连天都精确不到,这说明你没什么求生欲,我也拯救不了你。
某个时间点以后第 n 天是哪一天:
as.Date(329, origin = "2019-12-01")
## [1] "2020-10-25"
日期与时间
上面的内容是日期,相比来说,只处理日期的应用情形比较少,因为我们的仪器的采集频率都非常高,一般都是高于 1 Hz 的,所以多数据情况下我们都要日期和时间一起处理,下面我们看一下日期与时间(当然为使得内容不是那么的无聊,日期上我们稍微加了一个时间的内容,实际上应该让单位 units = days
才符合上一节的标题)。
日期与时间处理的软件包
R base 中的 POSIXt
,chron
,lubridate
都是很多人常用的工具,data.table
中的 IDateTime
主要偏重于速度,而且处于实验版本,不做介绍。
POSIXt
POSIXt 是 R 的一个类,又分为 "POSIXlt" 和 "POSIXct"。与此相关的函数有:
•as.POSIXct
•as.POSIXlt
•strptime
这三个函数有令人很容易迷惑混淆的地方,但是 stackoverflow 总是个能让人答疑解惑的地方:
First, there are two internal implementations of date/time: POSIXct, which stores seconds since UNIX epoch (+some other data), and POSIXlt, which stores a list of day, month, year, hour, minute, second, etc.
strptime
is a function to directly convert character vectors (of a variety of formats) to POSIXlt format.
as.POSIXlt
converts a variety of data types to POSIXlt. It tries to be intelligent and do the sensible thing - in the case of character, it acts as a wrapper to strptime.
as.POSIXct
converts a variety of data types to POSIXct. It also tries to be intelligent and do the sensible thing - in the case of character, it runs strptime first, then does the conversion from POSIXlt to POSIXct.
简单的说就是 as.POSIXlt
中 lt 指的是 local time,存储的是我们年月日星期等的属性,as.POSIXct
中 ct 指的是 calendar time,存储的是自 1970 年 1 月 1 日 0 时开始的秒数。
查看其属性我们就能直观的看到他们的差别:
x as.POSIXlt(Sys.time())y as.POSIXct(Sys.time())attributes(x)attributes(y)x$mday#y$mday
## $names
## [1] "sec" "min" "hour" "mday" "mon" "year" "wday" "yday"
## [9] "isdst" "zone" "gmtoff"
##
## $class
## [1] "POSIXlt" "POSIXt"
##
## $tzone
## [1] "" "CST" "CDT"
## $class
## [1] "POSIXct" "POSIXt"
## [1] 11
## [1] Error in y$mday : $ operator is invalid for atomic vectors
格式的问题
时间与日期格式的多变性是处理很多仪器数据时的麻烦事情,我觉得两个很重要的函数能帮我们解决大部分问题。
•format
# 24h - 12 h 的转换as.POSIXlt("2020-03-08 10:11:01 PM", format = "%Y-%m-%d %I:%M:%S %p")# 转换格式format(as.POSIXlt("08/04/06 22:11:00", format = "%m/%d/%y %H:%M:%S"), "%Y-%m-%d %H:%M:%S")
## [1] "2020-03-08 22:11:01 CST"
## [1] "2006-08-04 22:11:00"
•
strptime
strptime("08/04/06 22:11:00", format = "%m/%d/%y %H:%M:%S")
## [1] "2006-08-04 22:11:00 CST"
对于我们使用 ISO 8601 的国家来讲,默认的输出不用更改就是我们喜欢的格式。
DST
夏令时是我讨厌的东西,在我国的仪器也没这玩意,所以不讨论。我没查怎么处理,我觉得最简单的方法就是把时间加 1 h 就可以了。
时区
时区问题在我们国内基本也不会遇到,因为我们都适用一个时区的时间,但如果使用 gps 时钟,遇到了时区错误的问题,也可以通过指定 tz 方便的解决,例如,我们在 UTC +8,但是 GPS 时钟把我们搞成了 UTC+3,我们可以直接加上 5 个小时就可以修正这个错误了。
df "2020-3-8 18:12:12", "2020-3-8 18:13:12", "2020-3-8 18:14:12"))df$tz3 as.POSIXct(df$tz3)df$tz8 5*60*60df$tz8
## [1] "2020-03-08 23:12:12 CST" "2020-03-08 23:13:12 CST"
## [3] "2020-03-08 23:14:12 CST"
lubridate
lubridate
最大的优势是使得时间处理起来更容易了,函数名更容易记住:
例如将字符转为时间日期不需要指定格式:
library(lubridate)ymd("20101215")mdy("4/1/17")ymd_hms("20200314 17:01:05")
## [1] "2010-12-15"
## [1] "2017-04-01"
## [1] "2020-03-14 17:01:05 UTC"
上文提到的时间错误很容易直接更改时区解决,
df "2020-3-8 18:12:12", "2020-3-8 18:13:12", "2020-3-8 18:14:12"))df$tz3 "Antarctica/Syowa")df$tz3df$tz8 "Asia/Shanghai")df$tz8
## [1] "2020-03-08 18:12:12 +03" "2020-03-08 18:13:12 +03"
## [3] "2020-03-08 18:14:12 +03"
## [1] "2020-03-08 23:12:12 CST" "2020-03-08 23:13:12 CST"
## [3] "2020-03-08 23:14:12 CST"
当然,如果你不知道哪是 UTC +3,哪是 UTC +8,有一个很好的网站 (https://timezonedb.com/time-zones)[https://timezonedb.com/time-zones]。更多用法参考 (R for Data Science)[https://r4ds.had.co.nz/dates-and-times.html] 时间日期的章节,不赘述
chron
chron
是 chronological 的缩写,顾名思义是按时间发生顺序排列的。
chron
函数
用于产生时间序列的对象:
library(chron)dts "2020/02/20", "2020/02/21", "2020/03/1","2020/03/2", "2020/03/10"), format="y/m/d")dtstms "23:03:20", "22:29:56", "01:03:30","18:21:03", "16:56:26"))tmsx xattributes(x)
## [1] 02/20/20 02/21/20 03/01/20 03/02/20 03/10/20
## [1] 23:03:20 22:29:56 01:03:30 18:21:03 16:56:26
## [1] (02/20/20 23:03:20) (02/21/20 22:29:56) (03/01/20 01:03:30)
## [4] (03/02/20 18:21:03) (03/10/20 16:56:26)
## $format
## dates times
## "m/d/y" "h:m:s"
##
## $origin
## month day year
## 1 1 1970
##
## $class
## [1] "chron" "dates" "times"
生成了一个时间序列,不过日期的格式不那么让人喜欢。不过他支持时间直接从 day 加减:
dts[1]+2dts[1]+33dts[1]-99diff(x)
## [1] 02/22/20
## [1] 03/24/20
## [1] 11/13/19
## Time in days:
## [1] 0.9768056 8.1066435 1.7205208 7.9412384
结果也是以天来计算,有时候很方便。还可以直接按给定的标签返回日期的归属:
cut(dates("02/01/20") + 18:25, "weeks")dts "02/01/20")+ seq(5, 105, 15)dtscut(dts, "months")
## [1] week 1 week 1 week 1 week 1 week 1 week 2 week 2 week 2
## Levels: week 1 < week 2
## [1] 02/06/20 02/21/20 03/07/20 03/22/20 04/06/20 04/21/20 05/06/20
## [1] Feb 20 Feb 20 Mar 20 Mar 20 Apr 20 Apr 20 May 20
## Levels: Feb 20 < Mar 20 < Apr 20 < May 20
总而言之,恕我愚钝,我感觉这个包没太大用处。
python 时间日期
Python 的官方文档写的很好,归纳了掌握 Python 时间日期处理的四大杀器:datetime, calendar, time, dateutil
。我们从牵扯到最开始基本知识的 time
开始,它提供了一系列的与时间处理相关的函数,然后简单介绍一下 calendar
,着重介绍一下 datetime
和 dateutil
,因为后两者才是我们频繁要用的,前面两个也只是后面的基础。另外,据说 pytz
处理时区要比 datetime
自带的好用多了。
time
time
比较特殊,有些函数是分系统的,并不是所有函数都一定在电脑上有效,他们的官方文档里会专门标注:avalability:unix 的字样,以提醒我们 win 下用不了。简单看一下几个常用的函数:
•ctime
将 s 转换为英语国家喜欢的时间日期(还是 1970.1.1 为基准),如果不加参数返回当前时间:
from time import*ctime(888888)ctime()
## 'Sun Jan 11 14:54:48 1970'
## 'Sat Apr 11 11:27:52 2020'
•gmtime
将自基准日期的 s 转换为 UTC 时间。
gmtime(888888)
## time.struct_time(tm_year=1970, tm_mon=1, tm_mday=11, tm_hour=6, tm_min=54, tm_sec=48, tm_wday=6, tm_yday=11, tm_isdst=0)
•当然,如果格式不满意,time
也有 strptime strftime
,和 R 一样都遵循相同的标准,这里摘抄一下官方文档,就不再制作表格了:
Directive | Meaning | Notes |
---|---|---|
| Locale’s abbreviated weekday name. | |
| Locale’s full weekday name. | |
| Locale’s abbreviated month name. | |
| Locale’s full month name. | |
| Locale’s appropriate date and time representation. | |
| Day of the month as a decimal number [01,31]. | |
| Hour (24-hour clock) as a decimal number [00,23]. | |
| Hour (12-hour clock) as a decimal number [01,12]. | |
| Day of the year as a decimal number [001,366]. | |
| Month as a decimal number [01,12]. | |
| Minute as a decimal number [00,59]. | |
| Locale’s equivalent of either AM or PM. | (1) |
| Second as a decimal number [00,61]. | (2) |
| Week number of the year (Sunday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Sunday are considered to be in week 0. | (3) |
| Weekday as a decimal number [0(Sunday),6]. | |
| Week number of the year (Monday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Monday are considered to be in week 0. | (3) |
| Locale’s appropriate date representation. | |
| Locale’s appropriate time representation. | |
| Year without century as a decimal number [00,99]. | |
| Year with century as a decimal number. | |
| Time zone offset indicating a positive or negative time difference from UTC/GMT of the form +HHMM or -HHMM, where H represents decimal hour digits and M represents decimal minute digits [-23:59, +23:59]. | |
| Time zone name (no characters if no time zone exists). | |
| A literal |
通过上面的例子我们已经可以看出,time
所谓的 UTC 格式并不是那么友好,他们属于 struct_time
类, 虽然我们能猜出其中的含义来,但是这里也列一下,算作备忘:
Index | Attribute | Values |
---|---|---|
0 |
| (for example, 1993) |
1 |
| range [1, 12] |
2 |
| range [1, 31] |
3 |
| range [0, 23] |
4 |
| range [0, 59] |
5 |
| range [0, 61]; see (2) in |
6 |
| range [0, 6], Monday is 0 |
7 |
| range [1, 366] |
8 |
| 0, 1 or -1; see below |
N/A |
| abbreviation of timezone name |
N/A |
| offset east of UTC in seconds |
也有时区相关设置,我们放在后面的内容内。
calendar
calendar
提供给我们与日历相关的模块,例如星期,默认是从周一开始作为,周日作为结束,当然可以使用 setfirstweekday()
来修改。我觉得和我们仪器数据的处理相关不大,我们简单看一下其中的一个函数,就明白了,它处理的内容,一般仪器都不这么显示:
from calendar import day_namefor i in day_name:print("today is ", i)
## today is Monday
## today is Tuesday
## today is Wednesday
## today is Thursday
## today is Friday
## today is Saturday
## today is Sunday
datetime
这应该是 Python 中使用最广泛的时间日期处理了,虽然感觉它处理的的方式有些别扭,但还是包含了我们所需要的常用的功能,datetime
有两个名字挺奇怪的对象,按照我的理解(当然不一定对,我看官方文档解释的挺繁琐的):
•aware,该类包含的信息很全,包括算法上的和政治时间上的调整,例如时区和 DST。也就是说该类对象能够这么应用:我可以通过该类对象包含的时区,换算为其他的时区的时间,也能够换算称准确的 unix 时间的秒。•naive,也就是说没有包含相关的时间信息,仅仅是一个时间。类似于 1 后面可以是 mm,m 或者 km,完全取决于使用者。如果不牵扯到时间转换,使用该类应该是非常方便的。
我们用简单的例子来看一下它的基本用法:
from datetime import datetime# 将字符转换为日期并提取信息str_today = "2020-3-21"today = datetime.strptime(str_today, "%Y-%m-%d")today.monthtoday.day
## 3
## 21
对我们来讲,提取月和日用到的不多,但是将 unix 时间和正常时间的互换用到的地方就多了。
# 当前时间日期now = datetime.now()datetime.timestamp(now)dt_stamp = 1234354353.1999datetime.fromtimestamp(dt_stamp)
## 1586575672.42083
## datetime.datetime(2009, 2, 11, 20, 12, 33, 199900)
需要经常计算的时间差,例如上文时区给搞错的例子,我们可以使用 timedelta 搞定:
from datetime import timedeltautc3_time = datetime.strptime("2020-3-21 9:10:30", "%Y-%m-%d %H:%M:%S")utc8_time = utc3_time + timedelta(hours = 5)utc8_time
## datetime.datetime(2020, 3, 21, 14, 10, 30)
当然 python
也可以浪漫的对纪念日直接计算
date_from = datetime(2009, 1, 18, 15, 20, 22)now = datetime.now()now - date_from
## datetime.timedelta(4100, 72450, 475784)
如果非要处理时区,可以使用 pytz
(这不是我说的)。我们用它来添加更改时区:
from pytz import timezoneutc8 = timezone("Asia/Shanghai")bj_time = utc8.localize(datetime(2020, 3, 21, 20, 45, 10))bj_time# 转换为美国东部时间east_us = timezone("US/Eastern")bj_time.astimezone(east_us)
## datetime.datetime(2020, 3, 21, 20, 45, 10, tzinfo=)
dateutil
dateutil
将自己定义为 datetime
的扩展,特别需要注意的是,他的安装为
pip install python-dateutil# 或conda install python-dateutil
而它处理起日期和时间来确实非常方便,我们只介绍比较重要的几个模块。
parser
parser
的目的在于直接处理一系列的杂乱的日期格式,而得到我们所需要的格式。也就是简化我们要操作的识别的步骤:
from dateutil.parser import*from dateutil.tz import*from datetime import*TZOFFSETS = {"CST": +28800}DEFAULT = datetime(2020, 4, 10)parse("Thu Apr 10 10:36:28 CST 2020", tzinfos=TZOFFSETS)parse("Thu Apr 10 10:36:28 CST 2020", tzinfos=TZOFFSETS)parse("2020 10:36:28 CST 25 Apr Thu", tzinfos=TZOFFSETS)# 当然可以忽略时区,多数情况下我们也不需要处理时区parse("Thu Apr 10 10:36:28 CST 2020", ignoretz=True)# 如果没有年,我们可以提供一个默认的选项,这在处理# 只有时间的数据时非常有帮助,或者说我们可以不用合并# 数据里的日期和时间,只用时间列,并给其设定一个默认# 值即可parse("Thu Sep 25 10:36:28", default=DEFAULT)# 对 ISO 格式的解析叶室毫无压力parse("2019-09-25T10:49:41")parse("2019-09-25T10:49:41.5-03:00")
## datetime.datetime(2020, 4, 10, 10, 36, 28, tzinfo=tzoffset('CST', 28800))
## datetime.datetime(2020, 4, 10, 10, 36, 28, tzinfo=tzoffset('CST', 28800))
## datetime.datetime(2020, 4, 25, 10, 36, 28, tzinfo=tzoffset('CST', 28800))
## datetime.datetime(2020, 4, 10, 10, 36, 28)
## datetime.datetime(2020, 9, 25, 10, 36, 28)
## datetime.datetime(2019, 9, 25, 10, 49, 41)
## datetime.datetime(2019, 9, 25, 10, 49, 41, 500000, tzinfo=tzoffset(None, -10800))
parser
的形式为:parser.parse(parserinfo=None, **kwargs)
,上面的例子中使用了 **kwargs
的 tzinfos
选项,可以提供一个时区名或别名,例如上面我们使用的 CST,在我们看来是中国标准时间,具体的时区名缩写可参考: https://www.timeanddate.com/time/zones/,该参数还可以提供一个时区的 offsets(以秒计量的),这就是我们上面解析的前两个日期的目的,转换为标准的时区。
rrule
rrule
是名副其实的时间尺,可以生成一系列不同尺度的时间序列:
from dateutil.rrule import*from dateutil.parser import*from datetime import*import pprintimport syssys.displayhook = pprint.pprint# 从起始时间开始的 3 天的时间list(rrule(DAILY, count=3, dtstart=parse("20200401T090000")))# 有截止日期的时间序列list(rrule(DAILY, dtstart=parse("20200401T090000"), until=parse("20200405T000000")))list(rrule(DAILY, interval=2, count=5, dtstart=parse("20200405T090000")))
## [datetime.datetime(2020, 4, 1, 9, 0),
## datetime.datetime(2020, 4, 2, 9, 0),
## datetime.datetime(2020, 4, 3, 9, 0)]
## [datetime.datetime(2020, 4, 1, 9, 0),
## datetime.datetime(2020, 4, 2, 9, 0),
## datetime.datetime(2020, 4, 3, 9, 0),
## datetime.datetime(2020, 4, 4, 9, 0)]
## [datetime.datetime(2020, 4, 5, 9, 0),
## datetime.datetime(2020, 4, 7, 9, 0),
## datetime.datetime(2020, 4, 9, 9, 0),
## datetime.datetime(2020, 4, 11, 9, 0),
## datetime.datetime(2020, 4, 13, 9, 0)]
relativedelta
relativedelta
的设计是用于替代已有的时间日期的特定组分或者表示时间的间隔:
from datetime import*from dateutil.relativedelta import*import calendarnow = datetime.now()today = date.today()nowdatetime(2019, 9, 17, 20, 54, 47, 282310)todaydate(2019, 9, 17)# 解决上文的 utc+3 和 utc+8 的问题now+relativedelta(hours=+5)# 可以指定月,轴,以及小时,注意不是赋值的话必须有正负号today+relativedelta(months=+1, weeks=+1, hour=10)# 可以直接显示日期差relativedelta(datetime(2009, 1, 18, 16, 0), today)
## datetime.datetime(2020, 4, 11, 11, 27, 52, 774166)
## datetime.datetime(2019, 9, 17, 20, 54, 47, 282310)
## datetime.date(2020, 4, 11)
## datetime.date(2019, 9, 17)
## datetime.datetime(2020, 4, 11, 16, 27, 52, 774166)
## datetime.datetime(2020, 5, 18, 10, 0)
## relativedelta(years=-11, months=-2, days=-23, hours=-8)
本文属于整理相关有用的软件包和基础信息,并非学习使用,具体用法还请看各个软件包的帮助文档。关于 R 和 Python 的时间处理,常用的就是这些内容。