Precreated axes with datetime ruler and time zones
20 views (last 30 days)
Show older comments
I would like to precreate an axes with a datetime XAxis ruler and then drop in lines with datetime objects for the 'xdata'. Everything works great until I give the line input time data a timezone. If I say the data is in 'UTC' time, I get an error:
'Cannot combine or compare a datetime array wit a time zone with one without a time zone.'
I'm guessing this in the guts of the XAxis ruler in which there are three parameters that appear to be datetime oriented. I tried to set all 3 of those parameters with the set function to datetime objects that have a time zone ('local'). But I still get the above error when attempting to add a line.
I have tried to manually set all the datetime parameters to datetime objects with no success.
How to I precreate an axes with the correct XAxis ruler to handle my datetime data that has a time zone? I think I will have to actually call the plot function to plot a line instead of calling the line function ... at least once.
% Trying to get this to work ...
% This works:
dtr = matlab.graphics.axis.decorator.DatetimeRuler;
ax = subplot(2,1,1,...
'XAxis',dtr);
drawnow % not sure why I need this ...
xdata = [datetime('yesterday'),datetime('now')]; % data does not have a time zone
line('parent',ax,'xdata',xdata,'ydata',1:2);
% This doesn't
dtr = matlab.graphics.axis.decorator.DatetimeRuler;
ax = subplot(2,1,1,...
'XAxis',dtr);
drawnow % not sure why I need this ...
xdata = [datetime('yesterday'),datetime('now')];
xdata.TimeZone = 'UTC'; % giving my data a time zone ...
line('parent',ax,'xdata',xdata,'ydata',1:2);
dtr = matlab.graphics.axis.decorator.DatetimeRuler;
ax = subplot(2,1,1,...
'XAxis',dtr);
get(dtr)
dtr.Limits.TimeZone
L = dtr.Limits
L.TimeZone = 'local'
L.TimeZone
mtv = dtr.MinorTickValues;
mtv.TimeZone = 'local'
mtv.TimeZone
tv = dtr.TickValues;
tv.TimeZone = 'local
tv.TimeZone = 'local'
set(dtr,'Limits',L,'MinorTickValues',mtv,'TickValues',tv)
set(dtr,'MinorTickValues',mtv,'TickValues',tv','Limits',L)
set(dtr,'TickValues',tv','MinorTickValues',mtv,'Limits',L)
dtr
ax
set(ax,'XTick',tv,'XLim',L)
% I'm going to have to hack it like this ... will have to realize the subplot capability myself
xdata = [datetime('yesterday'),datetime('now')];
xdata.TimeZone = 'local'
o = plot(xdata,1:2)
ax = gca;
xdata.TimeZone = 'UTC';
delete(o)
line('parent',ax,'xdata',xdata,'ydata',1:2);
1 Comment
dpb
on 12 Sep 2019
Probably worth a bug report for "quality of implementation" issue if not outright bug. Not surprising to me there are still warts in the relatively new datetime ruler object...it's not been around very long and is pretty complex.
One thing you can do is use NaN for the plotted "data" in the superfluous line so it won't ever actually be displayed--but will create the line handle.
Sometimes for such purposes I'll go ahead and deliberately pre-create the line handle(s) intending to later populate with real X/YData arrays and so having them already there may be a bonus rather than a detriment if reconsider how you're creating the end result just slightly.
Accepted Answer
Benjamin Kraus
on 17 Mar 2023
Edited: Benjamin Kraus
on 17 Mar 2023
I believe the issue you are facing is that the XAxis has a specific time zone that is initialized when you first call any plotting commands (like line). Technically, the DatetimeRuler has a "reference date" which is used to both determine the internal conversion between double and datetime and dictate the TimeZone of the ruler. This reference date also impacts tick picking (the DatetimeRuler will select ticks that fall on nice boundaries in the specified time zone).
By default, the reference date and time zone is determined from the data that is used when the XAxis is first initialized (via the plotting command). Anything you plot into that axes afteward will display using that reference date and time zone, and this time zone is the time zone that is used by all user-facing properties on the DatetimeRuler (like Limits and TickValues).
Prior to R2023a, there was no way to access the internal reference date, although you could figure it out by calling num2ruler(0, axis). There was also no way to change the internal reference date or time zone without clearing your axes and starting over.
Starting in MATLAB R2023a, you can now directly query the ReferenceDate, and you can update the time zone of the x-axis of existing plots by setting the ReferenceDate on the ruler.
For example:
d = datetime(2023,2,10,12,0,0,TimeZone='America/New_York') + minutes(0:60);
% When you call plot, the axes will be configured to use the
% "America/New_York" time zone.
plot(d,sin(1:numel(d)));
% Prior to R2023a, you could indirectly query the ReferenceDate like this:
ax = gca;
num2ruler(0,ax.XAxis)
% Starting in R2023a, you can query the current reference date and time zone like this:
ax.XAxis.ReferenceDate
ax.XAxis.ReferenceDate.TimeZone
% Prior to R2023a, the only way to change the reference date was to clear
% your axes and plot again.
% Starting in R2023a, you can change the reference date and time zone by setting the ReferenceDate on the XAxis.
ax.XAxis.ReferenceDate = datetime(2023,2,10,'TimeZone','Europe/London');
More Answers (1)
See Also
Categories
Find more on Dates and Time in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!