7.2  日期和时间元素

本小节将为读者介绍如何对指定日期和时间元素的数值进行提取,另外如何通过datetime的属性来对指定的元素进行赋值。MATLAB提供了如下函数进行元素操作,请见表3-12。

表3-12  日期和时间元素提取函数

函    数

说    明

函    数

说    明

将日历时间长度按单位级别分解为数值形式

将日历时间长度转换为固定时间长度

将时间点转换为时间长度

检测夏令时元素

检测是否是周末

检测时区,返回和UTC的时差

下面我们举例来说明如何从已有的datetime数组中提取日期和时间元素。然后将会介绍如何对指定元素通过对数组属性的设置来进行修改。

【例3-45】 日期和时间数组元素的提取。

首先创建一个测试用datetime数组。

>> t = datetime('now') + calyears(0:2) +calmonths(0:2) + hours(20:20:60)

04-Sep-2014 20:42:32   05-Oct-:42:32   06-Nov-2016 12:42:32

如果想提取数组中的“年”这一元素,那么只需要使用“.”这一符号加Year属性就可以了。

>> t_years = t.Year

2014        2015        2016

输出的t_years是一个数值数组。

同样的,如果想提取月这一元素,可以通过以下方法:

>> t_months = t.Month

9    10   11

在以上方法之外,用户可以通过函数来对日期和时间的各元素进行检索。例如要检索月份的话,那么就可以通过month函数来实现。

>> m = month(t)

9    10   11

通过使用month函数而不是Month属性来提取月份的全名:

>> m = month(t,'name')

'September'    'October'    'November'

同样的也可以使用year,quarter,week,hour,minute和second函数来分别提取时间数组t中的其他元素:

>> w = week(t)

36    41   46

这里返回的是数据所对应与当年第几周。

使用ymd函数可以同时提取年、月、日三个元素:

>> [y,m,d] = ymd(t)

2014        2015        2016

9    10   11

4     5    6

使用hms函数可以同时提取时、分、秒三个元素:

>> [h,m,s] = hms(t)

20    16   12

42    42   42

【例3-46】 日期和时间数组元素的修改。

对已有时间数组中的元素数值进行修改可以通过“.”加属性名来实现。

改变时间数组t中的年份,令其等于2014:

>> t.Year = 2014

04-Sep-2014 20:42:32   05-Oct-:42:32   06-Nov-2014 12:42:32

将时间数组t中的月份分别改成1月、2月、3月:

>> t.Month = [1,2,3]

04-Jan-2014 20:42:32   05-Feb-:42:32   06-Mar-2014 12:42:32

通过TimeZone属性更改时间数组的时区:

>> t.TimeZone = 'Europe/Berlin';

更改时间数组的显示格式:

>> t.Format = 'dd-MMM-yyyy'

04-Jan-2014   05-Feb-2014   06-Mar-2014

如果用户在赋值的时候给出的数值超出了正常范围,那么MATLAB会对相应的元素进行正常化处理。例如,日期的正常范围是1-31,如果将范围之外的数值赋值给数组,那么结果如下:

>> t.Day = [-1 1 32]

30-Dec-2013   01-Feb-2014   01-Apr-2014

这里月份和年份的数值同时做了调整,从而使结果是属于正常范围的。例如这里将January -1, 2014转化成为了December 30, 2013。

7.3  日期和时间计算与绘图

本小节将为读者介绍日期和时间的相关加、减、绘图操作。MATLAB提供了多种函数以供使用,见表3-13。

表3-13  日期和时间计算函数

函    数

说    明

函    数

说    明

日历代数差

判断是否是datetime数组

日历连续代数差

判断是否是duration数组

平移日期或者产生日期和时间序列

iscalendarduration

判断是否是calendar duration数组

判断元素是否在日期和时间区间内

判断是否是NaT元素(非时间元素)

【例3-47】 日历时间长度与时间数组相加。

将一个日历时间长度数组和日期January31, 2014相加:

>> t1 = datetime(2014,1,31)               %  测试时间数组

31-Jan-2014

>> t2 = t1 + calmonths(1:4)               %  将日历月相加

28-Feb-2014   31-Mar-2014   30-Apr-2014  31-May-2014

结果中的每一个时间点都是当月的最后一天。

使用caldiff 函数可以计算数组中相邻的一对时间点之差:

>> dt = caldiff(t2,'days')             % 计算数组各时间点之间的日历天数差

31d   30d  31d

从结果中可以看出,连续的几对时间点之间的差都是一个日历月,但是天数并不都是等于31天。

同样的我们可以对年份也进行类似的操作:

>> t2 = t1 + calyears(0:4)                  %  初始测试数组

31-Jan-2014   31-Jan-2015   31-Jan-2016  31-Jan-2017   31-Jan-2018

使用caldiff函数可以计算数组t2中相邻时间点之间的天数差:

>> dt = caldiff(t2,'days')

365d   365d  366d   365d

由结果可以看出,并不是每一年的天数都等于365天。

【例3-48】 计算两个日历时间点之间的时间差。

使用between函数可以计算两个日历时间点之间的年、月、日之差。

>> t1 = datetime('today')

02-Apr-2015

>> t2 = t1 + calmonths(0:2) + caldays(4)

06-Apr-2015   06-May-2015   06-Jun-2015

>> dt = between(t1,t2)

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)

26-Jul-2013   26-Jul-2015   26-Jul-2017  26-Jul-2019

01-Jun-2014

>> A < B

1     0    0     0

在A中的时间早于B中的时间情况下,逻辑运算符<将会返回逻辑值1(true)。

对比一个datetime数组和一个日期字符串:

>> A >= 'September 26, 2014'

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')

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')

01-Sep-2014 17:00:00 -0400

>> A < B

从结果可以看出洛杉矶时间下午4点在纽约时间下午5点之后。

下面我们来对duration数组之间的比较进行演示。

>> A = duration([2,30,30;3,15,0])           % 测试数据A

>> B = duration([2,40,0;2,50,0])            % 测试数据B

>> A >= B

从结果中可以看出,和B相比较,A的第一个元素较短,而第二个元素较长。

如果将一个duration数组和一个数值型的数组进行比较,那么数值型的数组将会被看作是天数(固定每天24小时)。

>> A < [1; 1/24]             % A和【1天  1小时】相比较

使用isbetween函数可以判断某一日期时间是否在一个时间区间内。

首先需要创建时间区间的两个边界时间点:

>> tlower = datetime(2014,08,01)      %  起点

>> tupper = datetime(2014,09,01)      %  终点

01-Aug-2014

01-Sep-2014

然后创建一个datetime数组,然后判断数组是否在所设定的时间区间内。

>> A = datetime(2014,08,21) + calweeks(0:2)

21-Aug-2014   28-Aug-2014   04-Sep-2014

>> tf = isbetween(A,tlower,tupper)

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:')

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])

24-Oct-2012 10:45:07

连续日期数值表示的是距离计时起点过去了多少天。在MATLAB里面,这个起点日期是January 0, 0000。日期数值通过小数来表示不满一天的情况,例如6 p.m等于0.75天。所以采用日期数值来表示'31-Oct-2003, 6:00 PM' 的话那就是.75。

【例3-53】 日期数值的转换。

使用datetime函数将日期数值转换为datetime数组。

>> t =datetime(.75,'ConvertFrom','datenum')

31-Oct-2003 18:00:00

【例3-54】 将datetime数组转换为日期数值。

一些MATLAB函数只接受日期数值输入但并不接受datetime数组输入。如果想要调用这些函数的话,那么就需要将datetime数组转换为日期数值格式,然后再调用函数。例如log函数只接受数值格式输入,不接受datetime数组。

假设用户有一datetime数组表示了一项实验的时间数据:

>> t = datetime('18-Jun-2014') +calmonths(1:4)

18-Jul-2014   18-Aug-2014   18-Sep-2014  18-Oct-2014

减去实验开始的时间就可以得到该时间点对应的实验所花时间长度:

>> dt = t - '1-Jul-2014'

408:00:00   1152:00:00   1896:00:00  2616:00:00

dt是一个duration数组。将dt使用years、days、hours、minutes或seconds转换为统一单位的数值,例如:

>> x = hours(dt)

408        1152        1896        2616

将此双精度数组输入到log函数中就可以进行相应的计算: