Loren on the Art of MATLAB

Turn ideas into MATLAB

MATLAB Data Types for Dates and Time, Part II

Once again we're going to hear from guest blogger Andrea Ho, who works for the MATLAB Documentation team here at MathWorks.

Contents

Last time, I introduced new data types for representing date and time data in MATLAB:datetimefor representing specific points in time,durationfor representing exact differences between points in time, andcalendarDurationfor representing flexible amounts of time such as months. Today, we'll look at how these data types help you to work with time zones, daylight saving time, and dates in languages other than English.

Interest Payments from a Swiss Bank

Last time, we looked at bank interest payments over the course of a year, without paying attention to the bank location. Let's do a similar analysis, but this time, our bank is located in Switzerland and we are in Phoenix, Arizona.

Suppose we opened a bank account on January 1, 2013, and the account pays interest monthly on the last day of each month. Create a sequence of dates in 2013 to represent when the bank account pays interest. Thedateshiftfunction can shift a dateandcreate a sequence based on the initial date in one line.

p0 = datetime(2013,1,1); p = dateshift(p0,'end','month',0:11)'
p = 31-Jan-2013 28-Feb-2013 31-Mar-2013 30-Apr-2013 31-May-2013 30-Jun-2013 31-Jul-2013 31-Aug-2013 30-Sep-2013 31-Oct-2013 30-Nov-2013 31-Dec-2013

Suppose our records indicate that we received interest payments at either 3 AM or 4 AM, depending on the month of the year. We can input this information to ourdatetimevectorp, by modifying itsHourproperty.

p.Hour = [4 4 3 3 3 3 3 3 3 4 4 4]'; p.Format ='dd-MMM-yyyy HH:mm'
p = 31-Jan-2013 04:00 28-Feb-2013 04:00 31-Mar-2013 03:00 30-Apr-2013 03:00 31-May-2013 03:00 30-Jun-2013 03:00 31-Jul-2013 03:00 31-Aug-2013 03:00 30-Sep-2013 03:00 31-Oct-2013 04:00 30-Nov-2013 04:00 31-Dec-2013 04:00

Our bank in Zurich, Switzerland, has sent us a file namedinterest_2013.txtthat contains interest amounts for each month of the year.

For English-language dates and times, you can use theImport Toolto import your data graphically. However, the dates in our file are written in German:

Date,Interest 31. Januar 2013 12:00,1.93 28. Februar 2013 12:00,4.28 31. März 2013 12:00,4.82 30. April 2013 12:00,1.23 31. Mai 2013 12:00,5.89 30. Juni 2013 12:00,2.26 31. Juli 2013 12:00,3.84 31. August 2013 12:00,5.82 30. September 2013 12:00,2.51 31. Oktober 2013 12:00,2.99 30. November 2013 12:00,6.17 31. Dezember 2013 12:00,2.65

For non-English language dates, we must import the data using functions. We will usereadtableto read the file data into a table. Use the%Dspecifier to read the first column of data asdatetimevalues and specify the format of the date strings within curly braces. The'DateLocale'name-value pair argument tells MATLAB how to interpret the date strings in the file. The value ofDateLocaleis a combination of a lowercaselanguage codeand an uppercasecountry code. For example,'de_CH'indicates German-language dates in Switzerland.

T = readtable('interest_2013.txt',...'Format','%{dd.MMMM yyyy HH:mm}D %f','DateLocale','de_CH')
T =日期的兴趣  _______________________ ________31.January 2013 12:00 1.93 28.February 2013 12:00 4.28 31.March 2013 12:00 4.82 30.April 2013 12:00 1.23 31.May 2013 12:00 5.89 30.June 2013 12:00 2.26 31.July 2013 12:00 3.84 31.August 2013 12:00 5.82 30.September 2013 12:00 2.51 31.October 2013 12:00 2.99 30.November 2013 12:00 6.17 31.December 2013 12:00 2.65

It appears that the bank's payments were made at noon each month, while our own records indicate otherwise. What happened? Our original times are based in Phoenix, whereas the imported times from the bank are based in Zurich.

By default,datetimevalues are not associated with any time zone. That is, they are "unzoned". Because we want to compare dates and times across geographic locations and therefore time zones, we should associate eachdatetimearray with a time zone. You can learn more about time zoneshere.

让我们为Phoenix-based设置时区datetimevector,p. Valid values for theTimeZoneproperty include names of time zone regions from theIANA Time Zone Database. Then, adjust the display format to show the UTC offset for each value.

p.TimeZone ='America/Phoenix'; p.Format ='dd-MMM-yyyy HH:mm Z'
p = 31-Jan-2013 04:00 -0700 28-Feb-2013 04:00 -0700 31-Mar-2013 03:00 -0700 30-Apr-2013 03:00 -0700 31-May-2013 03:00 -0700 30-Jun-2013 03:00 -0700 31-Jul-2013 03:00 -0700 31-Aug-2013 03:00 -0700 30-Sep-2013 03:00 -0700 31-Oct-2013 04:00 -0700 30-Nov-2013 04:00 -0700 31-Dec-2013 04:00 -0700

Unlike most of the United States, Phoenix does not observe daylight saving time and is always 7 hours behind UTC.

Now, specify that the bank's payment times are in Zurich's time zone.

z = T.Date; z.TimeZone ='Europe/Zurich'; z.Format ='dd-MMM-yyyy HH:mm Z'
z = 31-Jan-2013 12:00 +0100 28-Feb-2013 12:00 +0100 31-Mar-2013 12:00 +0200 30-Apr-2013 12:00 +0200 31-May-2013 12:00 +0200 30-Jun-2013 12:00 +0200 31-Jul-2013 12:00 +0200 31-Aug-2013 12:00 +0200 30-Sep-2013 12:00 +0200 31-Oct-2013 12:00 +0100 30-Nov-2013 12:00 +0100 31-Dec-2013 12:00 +0100

In Zurich, the time zone offset changes during the year because Zurich observes daylight saving time.

Now if we compare our payment times with the bank's data, we'll see that they are the same.

isequal(p,z)
ans = 1

Not Every Day Has 24 Hours

On what day of the week were interest payments made? We can use thedayfunction to extract the day name from each value inz.

d = day(z,'name')
d = 'Thursday' 'Thursday' 'Sunday' 'Tuesday' 'Friday' 'Sunday' 'Wednesday' 'Saturday' 'Monday' 'Thursday' 'Saturday' 'Tuesday'

The third payment date (March 31) falls on a Sunday. Suppose the bank shifted this payment date earlier by two days so that it would not fall on a weekend.

What happens if we subtract adurationof 2 standard, 24-hour long days to the corresponding payment date?

new_date = z(3) - days(2)
new_date = 29-Mar-2013 11:00 +0100

Notice that the new payment time is now 11 AM instead of noon because a daylight saving time shift occurred in Zurich on March 30, 2014.

To account for a daylight saving time shift in a calendar calculation, we should subtract 2calendar daysfrom the original payment date.

new_date = z(3) - caldays(2)
new_date = 29-Mar-2013 12:00 +0100

Now the payment time is at noon, and is consistent with the payment times during the rest of the year. If we calculate the exactdurationbetween the original payment date and the new payment date, we will see that the difference is not 48 hours (two 24-hour long days). Rather, the difference is 47 hours due to the daylight saving time change.

new_date - z(3)
ans = -47:00:00

Here's the big takeaway: When adatetimevalue is associated with a time zone that observes daylight saving time, it is affected by daylight saving time changes. To correctly account for such time changes, make sure you use日历时间instead of durations in calendar calculations involving days, months, or years.calendarDurationvalues account for non-constant lengths of time such as the length of a day, which is not always equal to 24 hours in some time zones.

Quarterly Statistics

Now we will calculate the mean of the interest payments for each quarter. Just like how thedayfunction can extract day names for eachdatetimevalue in an array, thequarterfunction lets us extract the quarter number.

q = quarter(z)
q = 1 1 1 2 2 2 3 3 3 4 4 4

Now we can calculate statistics for the interest payments associated with each unique value of ofq.

forii = 1:4 X = sprintf('Quarter %d',ii); disp(X) tf = q==ii; m_quarter = mean(T.Interest(tf))% T.Interest is a column containing interest values from% the text file we imported earlierend
Quarter 1 m_quarter = 3.6767 Quarter 2 m_quarter = 3.1267 Quarter 3 m_quarter = 4.0567 Quarter 4 m_quarter = 3.9367

Convert Date Numbers to Datetime

Now we've seen how to createdatetimevalues and how to import date and time data asdatetimevalues that can account for time zones and daylight saving time. But what if you currently have data in the form of serial date numbers? Fear not, there's an easy way to convert your existing data to more convenient datetime values. Let's start with an array of serial date numbers:

dn = (735600:31:735755)'
dn = 735600 735631 735662 735693 735724 735755

Use thedatetimefunction to easily convert the date numbers to datetime values.

p = datetime(dn,'ConvertFrom','datenum')
p = 01-Jan-2014 00:00:00 01-Feb-2014 00:00:00 04-Mar-2014 00:00:00 04-Apr-2014 00:00:00 05-May-2014 00:00:00 05-Jun-2014 00:00:00

An array of serial date numbers cannot account for a time zone, but you can add time zone information to thedatetimearray.

p.TimeZone ='America/New_York';

You can even export thedatetimearray in a different language. Let's translate the dates into German and then export them to a text file.

C = cellstr(p,'dd. MMMM yyyy','de_DE')
C = '01. Januar 2014' '01. Februar 2014' '04. März 2014' '04. April 2014' '05. Mai 2014' '05. Juni 2014'
T = table(C,rand(6,1),'VariableNames',{'Date','InterestRate'})
T = Date InterestRate __________________ ____________ '01. Januar 2014' 0.2785 '01. Februar 2014' 0.54688 '04. März 2014' 0.95751 '04. April 2014' 0.96489 '05. Mai 2014' 0.15761 '05. Juni 2014' 0.97059
writetable(T,'myfile.txt')

Your Thoughts?

Have you tried using thedatetime,duration, andcalendarDurationdata types? Let us know what you think by leaving a commenthere.




Published with MATLAB® R2014b

|
  • print
  • send email

Comments

到leave a comment, please clickhereto sign in to your MathWorks Account or create a new one.