7.2 日期和时间元素
本小节将为读者介绍如何对指定日期和时间元素的数值进行提取,另外如何通过datetime的属性来对指定的元素进行赋值。MATLAB提供了如下函数进行元素操作,请见表3-12。
表3-12日期和时间元素提取函数
函 数说 明函 数说 明
year年份minute分钟
hour小时second秒
day日quarter季度数
month月份week星期数
ymd 年月日hms 时分秒
split 将日历时间长度按单位级别分解为数值形式time 将日历时间长度转换为固定时间长度
timeofday将时间点转换为时间长度isdst 检测夏令时元素
isweekend检测是否是周末 tzoffset检测时区,返回和UTC的时差
下面我们举例来说明如何从已有的datetime数组中提取日期和时间元素。然后将会介绍如何对指定元素通过对数组属性的设置来进行修改。
【例3-45】 日期和时间数组元素的提取。
首先创建一个测试用datetime数组。
>> t = datetime('now') + calyears(0:2) +calmonths(0:2) + hours(20:20:60)
t =
04-Sep-2014 20:42:32 05-Oct-201516:42:32 06-Nov-2016 12:42:32
如果想提取数组中的“年”这一元素,那么只需要使用“.”这一符号加Year属性就可以了。
>> t_years = t.Year
t_years =
2014 2015 2016
输出的t_years是一个数值数组。
同样的,如果想提取月这一元素,可以通过以下方法:
>> t_months = t.Month
t_months =
9 10 11
在以上方法之外,用户可以通过函数来对日期和时间的各元素进行检索。例如要检索月份的话,那么就可以通过month函数来实现。
>> m = month(t)
m =
9 10 11
通过使用month函数而不是Month属性来提取月份的全名:
>> m = month(t,'name')
m =
'September' 'October' 'November'
同样的也可以使用year,quarter,week,hour,minute和second函数来分别提取时间数组t中的其他元素:
>> w = week(t)
w =
36 41 46
这里返回的是数据所对应与当年第几周。
使用ymd函数可以同时提取年、月、日三个元素:
>> [y,m,d] = ymd(t)
y =
2014 2015 2016
m =
9 10 11
d =
4 5 6
使用hms函数可以同时提取时、分、秒三个元素:
>> [h,m,s] = hms(t)
h =
20 16 12
m =
42 42 42
s =
32.9365 32.9365 32.9365
【例3-46】 日期和时间数组元素的修改。
对已有时间数组中的元素数值进行修改可以通过“.”加属性名来实现。
改变时间数组t中的年份,令其等于2014:
>> t.Year = 2014
t =
04-Sep-2014 20:42:32 05-Oct-201416:42:32 06-Nov-2014 12:42:32
将时间数组t中的月份分别改成1月、2月、3月:
>> t.Month = [1,2,3]
t =
04-Jan-2014 20:42:32 05-Feb-201416:42:32 06-Mar-2014 12:42:32
通过TimeZone属性更改时间数组的时区:
>> t.TimeZone = 'Europe/Berlin';
更改时间数组的显示格式:
>> t.Format = 'dd-MMM-yyyy'
t =
04-Jan-2014 05-Feb-2014 06-Mar-2014
如果用户在赋值的时候给出的数值超出了正常范围,那么MATLAB会对相应的元素进行正常化处理。例如,日期的正常范围是1-31,如果将范围之外的数值赋值给数组,那么结果如下:
>> t.Day = [-1 1 32]
t =
30-Dec-2013 01-Feb-2014 01-Apr-2014
这里月份和年份的数值同时做了调整,从而使结果是属于正常范围的。例如这里将January -1, 2014转化成为了December 30, 2013。
7.3 日期和时间计算与绘图
本小节将为读者介绍日期和时间的相关加、减、绘图操作。MATLAB提供了多种函数以供使用,见表3-13。
表3-13日期和时间计算函数
函 数说 明函 数说 明
between日历代数差isdatetime判断是否是datetime数组
caldiff日历连续代数差isduration判断是否是duration数组
dateshift平移日期或者产生日期和时间序列iscalendarduration判断是否是calendar duration数组
isbetween判断元素是否在日期和时间区间内isnat 判断是否是NaT元素(非时间元素)
【例3-47】 日历时间长度与时间数组相加。
将一个日历时间长度数组和日期January31, 2014相加:
>> t1 = datetime(2014,1,31) % 测试时间数组
t1 =
31-Jan-2014
>> t2 = t1 + calmonths(1:4) % 将日历月相加
t2 =
28-Feb-2014 31-Mar-2014 30-Apr-2014 31-May-2014
结果中的每一个时间点都是当月的最后一天。
使用caldiff 函数可以计算数组中相邻的一对时间点之差:
>> dt = caldiff(t2,'days') %计算数组各时间点之间的日历天数差
dt =
31d 30d 31d
从结果中可以看出,连续的几对时间点之间的差都是一个日历月,但是天数并不都是等于31天。
同样的我们可以对年份也进行类似的操作:
>> t2 = t1 + calyears(0:4) % 初始测试数组
t2 =
31-Jan-2014 31-Jan-2015 31-Jan-2016 31-Jan-2017 31-Jan-2018
使用caldiff函数可以计算数组t2中相邻时间点之间的天数差:
>> dt = caldiff(t2,'days')
dt =
365d 365d 366d 365d
由结果可以看出,并不是每一年的天数都等于365天。
【例3-48】 计算两个日历时间点之间的时间差。
使用between函数可以计算两个日历时间点之间的年、月、日之差。
>> t1 = datetime('today')
t1 =
02-Apr-2015
>> t2 = t1 + calmonths(0:2) + caldays(4)
t2 =
06-Apr-2015 06-May-2015 06-Jun-2015
>> dt = between(t1,t2)
dt =
4d 1mo 4d 2mo 4d
【例3-49】 datetime和duration数组的比较。
本例将为读者演示如何对datetime和duration数组进行比较。用户可以在两个datetime数组之间进行元素对元素的对比,也可以对两个duration数组采用逻辑运算符进行比较,例如>和<。
对比两个datetime数组,两个数组必须具有相同的尺寸或者其中一个是标量。
>> A = datetime(2013,07,26) +calyears(0:2:6)
>> B = datetime(2014,06,01)
A =
26-Jul-2013 26-Jul-2015 26-Jul-2017 26-Jul-2019
B =
01-Jun-2014
>> A < B
ans =
1 0 0 0
在A中的时间早于B中的时间情况下,逻辑运算符<将会返回逻辑值1(true)。
对比一个datetime数组和一个日期字符串:
>> A >= 'September 26, 2014'
ans =
0 1 1 1
读者还可以对比不同时区的时间。例如比较洛杉矶的September 1, 2014 at 4:00 p.m和同一天的纽约时间5:00p.m:
>> A = datetime(2014,09,01,16,0,0,'TimeZone','America/Los_Angeles',...
'Format','dd-MMM-yyyy HH:mm:ss Z')
A =
01-Sep-2014 16:00:00 -0700
>> B =datetime(2014,09,01,17,0,0,'TimeZone','America/New_York',...
'Format','dd-MMM-yyyy HH:mm:ss Z')
B =
01-Sep-2014 17:00:00 -0400
>> A < B
ans =
0
从结果可以看出洛杉矶时间下午4点在纽约时间下午5点之后。
下面我们来对duration数组之间的比较进行演示。
>> A = duration([2,30,30;3,15,0]) %测试数据A
>> B = duration([2,40,0;2,50,0]) %测试数据B
A =
02:30:30
03:15:00
B =
02:40:00
02:50:00
>> A >= B
ans =
0
1
从结果中可以看出,和B相比较,A的第一个元素较短,而第二个元素较长。
如果将一个duration数组和一个数值型的数组进行比较,那么数值型的数组将会被看作是天数(固定每天24小时)。
>> A < [1; 1/24] % A和【1天1小时】相比较
ans =
1
0
使用isbetween函数可以判断某一日期时间是否在一个时间区间内。
首先需要创建时间区间的两个边界时间点:
>> tlower = datetime(2014,08,01) % 起点
>> tupper = datetime(2014,09,01) % 终点
tlower =
01-Aug-2014
tupper =
01-Sep-2014
然后创建一个datetime数组,然后判断数组是否在所设定的时间区间内。
>> A = datetime(2014,08,21) + calweeks(0:2)
A =
21-Aug-2014 28-Aug-2014 04-Sep-2014
>> tf = isbetween(A,tlower,tupper)
tf =
1 1 0
【例3-50】 日期和时间数组的绘图。
首先创建一个datetime数组作为x轴。
>> t = datetime(2014,6,28) + caldays(1:10);
将y轴数据定义一个随机数组,然后绘制曲线。
>> y = rand(1,10);
>> plot(t,y);
得到的结果如图3-8所示。
图3-8 日期数组绘图
在默认情况下,plot函数会基于数据的范围自动选择刻度线。当用户放大或缩小图形时,刻度线会自动随之调整。另外用户还可以自定义刻度线格式,例如通过下面的语句就可以将刻度线定义为日-月-年的格式。
>> plot(t,y,'DatetimeTickFormat','dd-MMM-yyyy')
得到的结果如图3-9所示。
图3-9 指定刻度线格式
对于duration数组来说也可以使用类似的方式进行绘图。
首先创建一个duration数组,例如以30秒为步长,总时间3分钟的一个数组:
>> t = 0:seconds(30):minutes(3);
同时创建随机数组作为y轴数据:
>> y = rand(1,7);
在绘图过程中可以指定横轴刻度均以秒为单位:
>> h = plot(t,y,'DurationTickFormat','s');
得到的结果如图3-10所示。
7.4 日期和时间作为数值和字符
如果用户在使用2014a及以前版本,或者和其他使用之前版本的人共享代码时,这就需要处理存储为双精度数值或字符串形式的日期和时间数据。此外,用数值形式表示的日期和时间还可以适用于一些不接受datetime和duration数据类型的函数。
尽管datetime数组是表达时间点的最佳数据类型,但用户还可以通过以下三种形式来表示日期和时间:
(1)Date String:字符串,例如Thursday, August 23, 2012 9:45:44.946 AM
(2)Date Vector:一个1×6的数值向量,包含了年、月、日、时、分、秒,例如[2012 8 23 9 45 44.946]
(3)Serial Date Number — 一个数值,从January 0, 0000开始计算,例如7.3510e+005
采用元胞数组、矩阵等可以以数组形式存储上述各种类型日期时间数据。
用户可以使用datetime函数将上述类型数据转换为datetime数组。反过来,用户可以分别使用datenum、datevec或datestr函数将datetime数组转换为日期数值、日期向量或者日期字符串类型。
日期字符串就是由表示日期或者时间的字符组成,可以有多种格式,例如下面的字符串都是表示August 23, 2010 at 04:35:42 PM:
'23-Aug-2010 04:35:06 PM'
'Wednesday, August 23'
'08/23/10 16:35'
'Aug 23 16:35:42.946'
用户可以采用12时制或者24时制来进行记录。在记录的字符串中还可以加入连字符、空格、冒号来分割各个元素。例如:
>> d = '23-Aug-2010 16:35:42'
【例3-51】 日期字符串的转换。
使用datetime函数可以将字符串转换为datetime数组。由于输入字符串格式可能有很多种,用户最好指明输入字符串的格式从而提高运行效率。
>> t = datetime(d,'InputFormat','dd-MMM-yyyyHH:mm:ss:')
t =
23-Aug-2010 16:35:42
尽管日期字符串d和datetime标量t看起来非常相似,但是二者是不相同的。
>> whos d t
Name Size Bytes Class Attributes
t 1x1 121 datetime
d 1x20 40 char
日期向量就是一个1×6的双精度数值的数组,其中的数值除了秒以外都是整数,采用24时制的形式来表示。日期向量采用年月日时分秒的顺序来进行记录。例如[2012 10 24 10 45 07]表示的是10:45:07AM on October 24, 2012。
【例3-52】 日期向量的转换。
使用datetime函数将日期向量[2012 10 24 10 45 07]转换为datetime数组。
>> t = datetime([2012 10 24 10 45 07])
t =
24-Oct-2012 10:45:07
连续日期数值表示的是距离计时起点过去了多少天。在MATLAB里面,这个起点日期是January 0, 0000。日期数值通过小数来表示不满一天的情况,例如6 p.m等于0.75天。所以采用日期数值来表示'31-Oct-2003, 6:00 PM' 的话那就是731885.75。
【例3-53】 日期数值的转换。
使用datetime函数将日期数值转换为datetime数组。
>> t =datetime(731885.75,'ConvertFrom','datenum')
t =
31-Oct-2003 18:00:00
【例3-54】 将datetime数组转换为日期数值。
一些MATLAB函数只接受日期数值输入但并不接受datetime数组输入。如果想要调用这些函数的话,那么就需要将datetime数组转换为日期数值格式,然后再调用函数。例如log函数只接受数值格式输入,不接受datetime数组。
假设用户有一datetime数组表示了一项实验的时间数据:
>> t = datetime('18-Jun-2014') +calmonths(1:4)
t =
18-Jul-2014 18-Aug-2014 18-Sep-2014 18-Oct-2014
减去实验开始的时间就可以得到该时间点对应的实验所花时间长度:
>> dt = t - '1-Jul-2014'
dt =
408:00:00 1152:00:00 1896:00:00 2616:00:00
dt是一个duration数组。将dt使用years、days、hours、minutes或seconds转换为统一单位的数值,例如:
>> x = hours(dt)
x =
408 1152 1896 2616
将此双精度数组输入到log函数中就可以进行相应的计算:
>> y = log(x)
y =
6.0113 7.0493 7.5475 7.8694