This is not so much a programming question as it is a desire for clarification to understand the way the Matlab serial date number format works. I'm referencing Matlab serial date numbers and I would like to know how to convert them into calendar dates using the simplest means possible. Many of the references out there only instruct how to work with these numbers within Matlab itself, but I want to be able to make sense of these by hand using arithmetic to derive the dates they represent without the use of Matlab (if this is even possible).
From the research I have done already, I do understand that a Matlab timestamp is essentially a count of the number of days since January 1, 0000 and that the floating point numbers appended to it further represent specific hours, minutes, etc. I'm not as clear on how these break down however. The reference information out there is not very informative nor comprehensive and I'm struggling to understand how it works.
Say I have the timestamp 735071.64930556. Could anybody provide me with a formula to be able to derive the calendar date that this represents, or guide me through the process to convert it? From a programming standpoint, my purpose for wanting to understand this is so I can eventually write a converter to be able to handle this format within the application I'm developing. For now though, I simply wish to understand how the process works.
Thanks
Use datevec or datestr:
>> datevec(735071.64930556)
ans =
1.0e+003 *
2.0120 0.0070 0.0210 0.0150 0.0350 0.0000
>> datestr(735071.64930556)
ans =
21-Jul-2012 15:35:00
What makes your question a little bit difficult to answer is mostly the leap year / leap second problem. If you expect date values to exist only over a limited range of values, the problem is somewhat simpler (actually I am not sure how Matlab deals with the "lost days" when the world went from Julian to Gregorian calendars, for example - see http://en.wikipedia.org/wiki/Conversion_between_Julian_and_Gregorian_calendars for a hint of what I am talking about).
The hours-minutes-seconds part is relatively easy. When you have
datevalue = 735071.64930556;
You can compute:
rem = datevalue - floor(datevalue);
hours = floor(24*rem);
rem = 24 * rem - hours;
minutes = floor( 60 * rem );
rem = 60 * rem - minutes;
seconds = 60 * rem;
To get the year / month / day, your best bet is to use some built in function in the language of your choice (for many examples, see http://www.epochconverter.com/epoch/daynumbers.php ), or knock yourself out and create some lookup tables. If you have the date of the first of every month, the lookup would be fast; and from 0 CE until today, that would be only 2013 * 12 entries - not a very large table. Such a table could be created in Matlab and exported...
Related
In Elixir, you can use :calendar.datetime_to_gregorian_seconds/1 to convert an Erlang time into the number of seconds since Epoch. The problem is, just with the number of seconds, you can't differentiate between two events which happened in the same second.
The DateTime struct, which my dates are instances of, does store the microseconds component of the date, but doesn't give me an easy way to find the difference between two times.
Does anybody know of a way (preferably without the use of a library) to find the difference, in microseconds, between two DateTimes?
Pass the :microseconds option to DateTime.diff/3
iex(1)> x1 = DateTime.utc_now()
#DateTime<2018-02-17 06:27:33.291406Z>
iex(2)> x2 = DateTime.utc_now()
#DateTime<2018-02-17 06:27:39.692571Z>
iex(3)> DateTime.diff(x2, x1, :microseconds)
6401165
I have the following values in Excel:
Bed time 19:34:00
Get up time 07:04:00
Time in bed 11:30:00
Sleep start 19:42:00
Sleep end 07:00:00
I want to import them into MATLAB and do some calculation on these time values such as subtraction. The time values look like this after importing:
0.8153
0.2944
0.4792
0.8208
0.2917
and obviously doing calculation on them would be nonsense. Would any body help me with this issue? I have stuck with it for few days, and no progress yet.
Thanks in advance,
As assylias pointed out, these are fractions of days. You can use the datestr function to convert it to human-readable strings with formatting option conveniently.
e.g.:
datestr(0.2917, 'HH:MM:SS')
ans =
07:00:02
Calculations such as subtractions can be done on the raw values before
conversion.
E.g: get duration of sleep.
start = 0.8208
stop = 0.2917
datestr(stop-start, 'HH:MM')
ans =
11:18
Even works for intervals that span over midnight.
I am trying to read time-coordinate data from a netCDF file using matlab. I have a netCDF file (which I created) that has a time variable in the format of a double corresponding to the number of hours from a specific time (see below).
Variable attributes:
double time(Time) ;
time:standard_name = "Time" ;
time:units = "hours since 2002-01-01 0:0:0" ;
time:calendar = "proleptic_gregorian" ;
When I read the time variable using ncread) into matlab, it just prints out an integer e.g.,1. However, if I use "ncdump" to explore the file, I see the time variable in it's coordinate time e.g., 2002-01-01 01.
Specifically: "ncdump -t -v time ncfile.nc"
I'm relatively new to matlab, and I was wondering if anyone knew if there was a similar, or an equally simple, way to read this time variable as its coordinate time into matlab, either as a string, or numerical date. Specifically, I would like to avoid having to parse the attribute string and code up a bunch of pointers and conditions to convert the integer data to an actual date.
Alternatively, should I just create a new time variable in these files that is just an array of dates as strings?
Any information is very much appreciated!
Thanks!
NetCDF stores time as an offset from an epoch. From your variable attribute, your epoch is 2002-01-01 0:0:0, and the time is hours since then. Matlab has a similar methodology called date numbers, although it is based off of days since an epoch (which they call pivot years). There are two functions that you should look into: datenum and datestr. The first converts a string into a date number and the other converts a date number into a date string.
You can convert your time variable into a compatible Matlab date number by dividing by 24 and then use the datestr function to format it however you like. Here is a simple example:
>> time = [1;2;3;4];
>> datestr(time./24+datenum('2002-01-01 0:0:0'))
ans =
01-Jan-2002 01:00:00
01-Jan-2002 02:00:00
01-Jan-2002 03:00:00
01-Jan-2002 04:00:00
Look at the Matlab help files associated with the two functions and you can format the date output however you like.
I would like to parse/convert DateTime (or FileTime) data type which is int64 and measured in "ticks" which are 100-nanoseconds units, to a datenum or a better date & time format in Matlab.
I must use a counter with a high resolution 64bit as the difference between time stamps can be a couple of microseconds and the "spacing" isn't even.
Using latest Matlab version, the "ticks" variable is read as a string..
Any recommendations?
Thank you for your help
Datenums probably won't represent this effectively. They are doubles, an approximate type, with 1.0 = 1 day; the resolution limit for recent dates is about 10 microseconds. Also, the datenum related functions aren't written for high precision processing, and probably won't work well here.
>> datenum_precision = eps(now)
datenum_precision =
1.1642e-010
>> millisecond = 1.0/(24*60*60*1000)
millisecond =
1.1574e-008
>>
You're probably better off creating your own class that wraps the "ticks" as uint64 and provides methods for converting to human-readable presentation (like datestr()), doing addition and subtraction, parsing the strings you're getting to the uint64 values, and so on. Something with an interface like this.
classdef filetime
properties
tick; % An array of uint64 ticks
end
methods (Static = true)
out = parse(str); % Parse strings to #filetime
end
methods
out = filetimestr(obj); % human-readable strings
out = minus(a,b);
out = plus(a,b);
out = sort(obj);
out = datenum(obj); % maybe a lossy conversion to datenum, for convenience
end
end
You'll need R2010b to do arithmetic on 64-bit ints; older versions don't support it.
The tricky part would be if you wanted to do plots using the filetimetick objects; the Handle Graphics plots don't support user-defined objects.
You can convert your numbers to MATLAB's serial date with a simple equation:
step = 1e-7; % 100 nanosec
ticks = int64(250000);
timenum = double(ticks)*step/24/60/60;
First, for very large integer values converting to double might loose precision. If this is the case you probably better to stay with your numbers without converting to serial date.
Second, DATESTR/DATETICK functions support precision up to milliseconds. Try:
datestr(timenum,'HH:MM:SS.FFF')
So, think about it and please answer Andrew's comment - what do you need this conversion for?
D is a uint64 value of 100 ns since 01-01-1601, the result must be a datenum. This means days passed since 00-Jan-0000.
step = 100E-9; % 100 nanoseconds
step = step/(24*60*60); %fraction of a day
D = datenum('01-01-1601')+double(D)*step;
%D is now a datenum
Modern version using datetime (matlab >2014b)
%uint64 value of 100 ns since 01-01-1601
step = 100E-9; % 100 nanoseconds
step = step/(24*60*60); %fraction of a day
D = datetime('01-01-1601')+days(double(D)*step);
As mentioned above, both methods lose some of the accuracy that we had. In the case of datetimes this can probably be circumvented. It happens at double(D)*step because D is big for current dates. Many nanoseconds have passed since 1601. By converting D to a more recent offset one could get a more accurate conversion.
I was hoping someone that is good with math and loops could help me out. I'm writing a program in Objective C where I need to come up with a way to do a cycle. If you don't know Objective C I would appreciate any help in pseudo code just to help me figure this out.
What I need is a scale that is based on two dates. I know this will be some sort of loop but not sure how to figure it out.
For instance, lets say that the first date is 5/25/1976 and the second date is 9/25/2009. Every 25 days there will be a "peak" so it's value will be 100. If I divide 23 in half I get 12 (rounded) so it would be the opposite or "valley" so it's numerical value would be 0. In other words on the 23rd day it would be at 100 but then on the 24th day it would start going back down and then bottom out 12 days later and then start the cycle back up and top out again at 23 days.
What I need to be able to do is find the numerical value for any given date in between any two given dates.
Thanks for any help you can offer!
value = 100*cos(2*pi*(numDays/25))
Or something like that.
Calculate the difference in days (optionally in fractional days too) between the starting point and the day you want the value for.
Divide by the cycle period (could be 23 or 25 according to the question).
Take the fractional part.
Apply the correct periodic function - for example, either sin() or cos(), appropriately scaled for the trigonometric functions (multiply the fraction by 2π).
You could simulate the shape by values out of a table describing the values indexed on days into the period (so you would use waveform[Δt mod period] to determine the value).
The NSDate class has a method timeIntervalSinceDate that will give you then number of seconds between two dates. You could calculate the number of days between two dates like this:
- (double) daysBetweenStart:(NSDate*)start end:(NSDate*)end
{
return [start timeIntervalSinceDate:end] / 86400.0; // seconds in a day
}
You could use this to compute a step function based on that:
- (double) someDescriptiveFunctionName:(NSDate*)date fromDate:(NSDate*)start
{
double days = [self daysBetweenStart:start end:date];
if ((int) days % 23 == 0)
return 100.0;
else
return 0.0;
}
This function returns 100.0 if the given date is between 23 and 24 days from the start, and 0.0 otherwise. You could substitute 23 for whatever period you like. I'm not sure if this is what you wanted, so clarify your question if it wasn't.
Disclaimer: This is Cocoa. Hopefully it's the same as iPhone Cocoa?