Where is the date tossing useful?

I am reading Phobos docs. Sometimes I cannot understand the logic of some methods.

Rollback by date

Adds the specified number of years or months to this date. A negative number will be subtracted. The difference between rolling and adding is that rolling does not affect larger units.

Maybe Phobos doesn't understand well, maybe I don't understand where this can be useful.

If I add, for example, 200 days to 2013-07-01, I expect to get 2014, but not 2013.

Can anyone explain the logic?

+3


source to share


2 answers


roll

also present in Java ... The only time I remember ever using it in any language but using a little date picker widget. There are separate fields for each thing: month, day, year, and you want the user to be able to scroll through the days without increasing the month as they are separate fields. (Suppose it's set to 30 and they want to select 1st. The fastest way is to just press the up arrow and let it flip.)

There may be other uses, I just don't remember them right now. Even when I was doing tech support some time ago (patented unfortunately), I never used the roll method, but there might be potential. ical is the standard for recurring events in calendars and there are some tricky things and a few different ways to implement it.

In the comment, you also ask why you can't add

days. The reason is that adding days is pretty trivial and covered opBinary

:

datetime += 5.days; // works

      



This does NOT work for months because months are of variable duration. This is when the method add

comes in to help: let's say it's January 30th and you add one month. You can only add 31 days as there are 31 days in January. That would land you on March 2nd (I think I'm doing it in my head) ... but January 30th + 1 month might also take February 28th. Or maybe February 29th. Suppose you pay your monthly bill at the end of the month, the number of days between these periods will change.

The method add

handles this and gives you the option to fall on the last day or spill over into the next month.

Although, I would say that days have no static length .... consider a DST transition. (Or leap seconds, but handling them would be a nut). Maybe we can ask JMD.

+5


source


So the short answer is that Adam is right , and roll

there is specifically for handling date pickers and similar use cases , and add

there is especially for handling months and years, because he Duration

can't (since months and years are not converted to hecto-nanoseconds, not knowing the starting point). But I will attach a more detailed answer to it if that clarifies the situation.

DateTime

, Date

and TimeOfDay

are intended for calendar operations. They are not related to the system clock, they have no concept of time zone, and they contain the date / time parts as separate units (year, month, day, hour, etc.) internally. So, when you set a field hour

to DateTime

, you are literally just adjusting one of the member variables DateTime

. And when you add to them Duration

, it needs to be split to add to each module individually, and so doing something like adding Duration

from 7 hours can increase more than just the field hour

. eg.

auto dt = DateTime(2015, 8, 2, 20, 0, 0);
dt += hours(7);
assert(dt == DateTime(2015, 8, 3, 3, 0, 0));

      

And since it Duration

stores its value inside hecto-nanoseconds, you don't necessarily add to a specific unit anyway. those. it doesn't look like the += hours(7)

one that specifically adds to the field hour

. He adds a certain amount of hecto-nanoseconds in general DateTime

and needs to figure out how this affects each of the units, rather than affecting a specific unit. eg.

auto dt = DateTime(2015, 8, 2, 20, 0, 0);
dt += hours(7) + minutes(5) + seconds(22);
assert(dt == DateTime(2015, 8, 3, 3, 5, 22));

      

roll

on the other hand, specifically to add to a specific unit, without affecting any of the others. As Adam correctly identified, its main use case was for spin control and the like. In the date picker dialog, where you end up adjusting a specific unit of time by some amount, and you don't want to influence other units, you are adjusting. So, if you add 7 hours, you don't get a day gain, just hours.

auto dt = DateTime(2015, 8, 2, 20, 0, 0);
dt.roll!"hours"(7);
assert(dt == DateTime(2015, 8, 2, 3, 0, 0));

      

Now things get a little funnier with months and years, because they don't have a fixed length. And therefore Duration

does not support them. You cannot say that x

hecto-nanoseconds is equivalent to y

months or z

years. But while it Duration

doesn't make sense for months or years, we still want to be able to add months and years to Date

or DateTime

. So we have add!"years"

and add!"months"

to deal with this, and it allows you to control some oddities, such as adding 1 month to January 31st should end in late February or early March (since there is no February 31st).

None of this takes into account any time zone. This is purely a matter of calendar time. add

and roll

are purely calendar operations, but +=

implemented in DateTime

, Date

and TimeOfDay

is a calendar-based operation. It takes years, months, days, etc. into account when it does its calculations (and cannot do otherwise in its case, since the units are shared between their member variables).



And then we have SysTime

. It is designed to represent the system time (which means taking into account the time zone). However, the only way to avoid problems with DST and the like is to always keep the time in UTC. This way it SysTime

always stores its time inside UTC (in hectoniseconds) and uses the object TimeZone

( LocalTime

by default) to convert it to a specific timezone only when needed. This avoids all sorts of annoying time-related errors. And anyone who works at system time should use SysTime

, not DateTime

, Date

or TimeOfDay

.

So when you add in SysTime

with +=

, you are really adding hecto-nanoseconds from Duration

to hecto-nanoseconds that it SysTime

uses internally. No calendaring is happening (and if they did, you would have a lot of DST related errors). SysTime

is not calendar at all. In order to perform any calendar operations, the SysTime

hecto-nanoseconds it contains internally must be converted to whatever it represents in terms of a date in the Gregorian calendar (using an object TimeZone

to account for the time zone).

However, to be user-friendly, SysTime

it provides a lot of calendar properties and functions performed DateTime

(eg, year

, month

, day

, hour

,, etc. and functions add

, and roll

). To support this, it basically finishes converting to Date

or DateTime

internally to execute them, which means considering the time zone and which potentially means introducing DST errors if not used correctly. And in some cases, it's annoyingly ineffective. For example, if you have a variable SysTime

calledst

auto year = st.year;
auto month = st.month;
auto day = st.day;

      

converts st

to Date

three times, while it would be more efficient to simply convert to Date

clearly and get units there. So this user-friendliness is a bit of a double-edged sword.

It also begs the question that Adam raised the issue of how to add and roll with DST. roll

and add

on SysTime

interact with Date

or DateTime

internally, and this takes DST into account as converting from SysTime

to Date

or DateTime

converting it from UTC to regardless of its object TimeZone

. So, roll

u add

work on SysTime

exactly how they work on DateTime

- because they get converted to DateTime

and from.

But, as I said, +=

to SysTime

simply adds Duration

to its UTC time. Thus, it is SysTime

not possible to add units of measure less than months and take into account DST. You would explicitly convert to DateTime

, use +=

, and then convert it back to SysTime

, which is a little ugly, but that's not what you would normally want. I suppose we could make the SysTime.add

units work in less than months, but then you just end up with people using that and end up with DST related errors when they should have used +=

but didn't understand the difference.

Indeed, at this point I am asking the question that adding these calendar features to SysTime

it was smart and that it actually ends up hurting usability rather than helping as intended. But I doubt that we could change it at this point - or more accurately, while we could change it, I doubt that giving up those features to SysTime

and forcing people to change their code would be worth the pain it can call. If I could repeat it, I would seriously consider not doing calendar operations on SysTime

.

Either way, we hope the wall of text was illuminating enough to be worth your time.

+5


source







All Articles