Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting Matlab's datenum format to Python

Tags:

python

matlab

I just started moving from Matlab to Python 2.7 and I have some trouble reading my .mat-files. Time information is stored in Matlab's datenum format. For those who are not familiar with it:

A serial date number represents a calendar date as the number of days that has passed since a fixed base date. In MATLAB, serial date number 1 is January 1, 0000.

MATLAB also uses serial time to represent fractions of days beginning at midnight; for example, 6 p.m. equals 0.75 serial days. So the string '31-Oct-2003, 6:00 PM' in MATLAB is date number 731885.75.

(taken from the Matlab documentation)

I would like to convert this to Pythons time format and I found this tutorial. In short, the author states that

If you parse this using python's datetime.fromordinal(731965.04835648148) then the result might look reasonable [...]

(before any further conversions), which doesn't work for me, since datetime.fromordinal expects an integer:

>>> datetime.fromordinal(731965.04835648148) 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: integer argument expected, got float

While I could just round them down for daily data, I actually need to import minutely time series. Does anyone have a solution for this problem? I would like to avoid reformatting my .mat files since there's a lot of them and my colleagues need to work with them as well.

If it helps, someone else asked for the other way round. Sadly, I'm too new to Python to really understand what is happening there.

/edit (2012-11-01): This has been fixed in the tutorial posted above.

like image 688
Fred S Avatar asked Dec 20 '12 05:12

Fred S


2 Answers

You link to the solution, it has a small issue. It is this:

python_datetime = datetime.fromordinal(int(matlab_datenum)) + timedelta(days=matlab_datenum%1) - timedelta(days = 366)

a longer explanation can be found here

like image 154
carlosdc Avatar answered Sep 19 '22 17:09

carlosdc


Using pandas, you can convert a whole array of datenum values with fractional parts:

import numpy as np
import pandas as pd
datenums = np.array([737125, 737124.8, 737124.6, 737124.4, 737124.2, 737124])
timestamps = pd.to_datetime(datenums-719529, unit='D')

The value 719529 is the datenum value of the Unix epoch start (1970-01-01), which is the default origin for pd.to_datetime().

I used the following Matlab code to set this up:

datenum('1970-01-01')  % gives 719529
datenums = datenum('06-Mar-2018') - linspace(0,1,6)  % test data
datestr(datenums)  % human readable format
like image 27
jonas Avatar answered Sep 16 '22 17:09

jonas