9

I have an array of Epoch milliseconds (array of numbers) in Matlab. I would like to convert these into UTC date-time format, such as DD-MM-YYYY HH:MM.

Is there a pre-defined Matlab way to do this or will I have to write my own function?

Erol
  • 6,478
  • 5
  • 41
  • 55

3 Answers3

22

Suppose, you start with a vector time_unix, then:

>> time_unix = 1339116554872; % example time
>> time_reference = datenum('1970', 'yyyy'); 
>> time_matlab = time_reference + time_unix / 8.64e7;
>> time_matlab_string = datestr(time_matlab, 'yyyymmdd HH:MM:SS.FFF')

    time_matlab_string =

    20120608 00:49:14.872

Notes:

1) See the definition of matlab's time.

2) 8.64e7 is number of milliseconds in a day.

3) Matlab does not apply any time-zone shifts, so the result is the same UTC time.

4) Example for backward transformation:

>> matlab_time = now;
>> unix_time = round(8.64e7 * (matlab_time - datenum('1970', 'yyyy')))

unix_time =

             1339118367664

To summarize, here are two functions:

function tm = unix2matlab(tu)
    tm = datenum('1970', 'yyyy') + tu / 864e5;
end
function tu = matlab2unix(tm)
    tu = round(864e5 * (tm - datenum('1970', 'yyyy')));
end

The matlab time here is numeric. You can always convert it to string using datestr()

Update for nanoseconds

time_unix_nanos = 1339116554872666666;
millis = round(time_unix_nanos / 1e6);
nanos = time_unix_nanos - 1e6 * millis;
time_matlab = unix2matlab(millis);
s = [datestr(time_matlab, 'yyyymmdd HH:MM:SS.FFF'), num2str(nanos)];

        s =
        20120608 00:49:14.872666666
Serg
  • 13,470
  • 8
  • 36
  • 47
  • Awesome. Little caveat that some unix timestamps are in micro- (or even nano-) seconds now, so that `864e5` may need to be `864e8` or even `864e11`. – charleslparker Dec 06 '12 at 18:22
  • I am getting the following error "Error using datevecmx The datevecmx function only accepts double arrays. " – Maxtron Oct 09 '18 at 15:33
  • >> `... micro or nano...`, well, just divide it accordingly – Serg Nov 03 '18 at 22:56
  • apply double(). By default all numbers in matlab are doubles, so `time_unix = 1339116554872;` is also double – Serg Nov 03 '18 at 22:58
1

I tried the above code, but the results were wrong. I realised the main error is related to the awkward definition of the Unix time (epoch time). Unix time (epoch time) is defined as the number of seconds after 1-1-1970, 00h:00, not the number of **milli**seconds (http://en.wikipedia.org/wiki/Unix_time). With this definition, the Unix time should therefore be divided by 8.64e5 instead of 8.64e7.

In addition, datenum('1970', 'yyyy') does not seem to result in the desired reference time of 1-1-1970, 00h:00.

Here's my improved code:

tMatlab = datenum (1970,1,1,0,0) + tUnix / 86400;
mbrennwa
  • 581
  • 1
  • 3
  • 11
  • 8.64e7 is number of milliseconds in a day. If your timestamp is in seconds, you should use 8.64e4 (i.e. 86400), not 8.64e5 – Serg Nov 03 '18 at 23:16
0

Serg's answer is what I normally use, when I'm working in MATLAB. Today I found myself wanting to do the conversion to date in MATLAB as the title says - without the datestring conversion  specified in the question body - and output the date number from the shell.

Here is what I settled on for the rounded date number:

TODAY_MATLAB="$[719529 + $[`date +%s` / 24/60/60]]"

This is really just the bash equivalent of what you would expect: 719529 is the datenum of the epoch (1970-01-01 or datenum(1970,1,1) in MATLAB). I'm also fumbling through ksh lately and it seems this can be done there with:

TODAY_EPOCH=`date +%s`
TODAY_MATLAB=`expr $TODAY_EPOCH / 24 / 60 / 60 + 719529`

As a side exercise, I added the decimal portion back onto the date in bash - I didn't bother in ksh, but it's only arithmetic and goes similarly:

N_DIGITS=7
FORMAT=$(printf "%%d.%%0%dd" $N_DIGITS)

NOW_EP_SEC=`date +%s` 
SEC_PER_DAY=$(( 24*60*60 )) 
NOW_EP_DAY=$(( $NOW_EP /$SEC_PER_DAY ))  
SEC_TODAY=$(( $NOW_EP_SEC - $NOW_EP_DAY*$SEC_PER_DAY )) 

TODAY_MATLAB="$(( NOW_EP_DAY+719529 ))"
FRACTION_MATLAB="$( printf '%07d' $(( ($SEC_TODAY*10**$N_DIGITS)/SEC_PER_DAY )) )"
MATLAB_DATENUM=$( printf $FORMAT $TODAY_MATLAB $FRACTION_MATLAB )

echo $MATLAB_DATENUM
sage
  • 4,863
  • 2
  • 44
  • 47