Skip to content

Add DateIterator and make consistent date type APIs #436

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

jmh530
Copy link
Contributor

@jmh530 jmh530 commented Jul 19, 2022

Will use with between function to add support for period function (to return slice of Dates).

Had to make some adjustments to make each of the date types have a consistent API. I changed the addXXX to an incrementCopy, but really the important thing is the increment part of it. I left date._addDays since that was the only remaining addXXX function in `date and didn't want to get too ahead of myself.

@9il
Copy link
Member

9il commented Jul 20, 2022

why not use iota?

date + 100.iota!uint;

@jmh530
Copy link
Contributor Author

jmh530 commented Jul 20, 2022

date + 100.iota!uint;

That only works for days. Even if you did something a stride, then it is constant by days. So for instance, skipping every 30 days is not the same as skipping every month.

I want to add a function, call it period or sequenceDate or iotaDate or something else, that takes a Date/YearMonth/YearQuarter and a length N and returns a 1-dimensional slice of length N that returns that starting date and the subsequent values incorporating units. So for instance, period!"months"(Date(2020, 1, 1), 4) would return [Date(2020, 1, 1), Date(2020, 2, 1), Date(2020, 3, 1), Date(2020, 4, 1)]. You can't easily replicate that behavior with your solution because the length of months changes and you have leap years.

@jmh530
Copy link
Contributor Author

jmh530 commented Jul 20, 2022 via email

@jmh530
Copy link
Contributor Author

jmh530 commented Jul 20, 2022

One thing that might make this somewhat simpler for YearMonth and YearQuarter is to only store _months and _quarters similar to _julianDays in Date. This would enable you to take an iota-like approach for these. There would still be a problem for Date that I mentioned above.

@9il
Copy link
Member

9il commented Jul 21, 2022

The following solution requires much less changes and additional.

map!Date(YearMonth(2020, 1) + 4.iota!uint)

One thing that might make this somewhat simpler for YearMonth and YearQuarter is to only store _months and _quarters similar to _julianDays in Date. This would enable you to take an iota-like approach for these. There would still be a problem for Date that I mentioned above.

Not really. += -= + - operation can be defined for YearMonth and YearQuarter without changing their representation. Just convert the pair to int adjust, convert back to a pair.

@9il
Copy link
Member

9il commented Jul 21, 2022

Yes, there are some special cases like leap year and different amount of days in a month. However, this day convention are much more complex and requires. There are multiple conventions of adding a month to a date that will result different adjusted dates.

@jmh530
Copy link
Contributor Author

jmh530 commented Jul 22, 2022

map!Date(YearMonth(2020, 1) + 4.iota!uint)

I'm open to suggestions, but this doesn't work currently because opBinary for YearMonth is const. If you remove const from it, then the result is not correct. It goes January, February, April, July. It also says you can make add const or inout, but that has its own issues.

@9il
Copy link
Member

9il commented Jul 22, 2022

I would suggest making an MR from scratch and adding only opBinary and opOpAssign to YearMonth and YearQuarter.

@jmh530
Copy link
Contributor Author

jmh530 commented Jul 22, 2022

@9il You added opBinary for YearMonth as part of PR #431. The problem is that it uses the add function, which returns a reference to this. I assumed that you did it this way for a reason, for instance to be compatible with the code base you primarily work on, so I didn't want to modify it. This is why I added the increment and incrementCopy functions, because adding with a reference doesn't work when iterating. It also wouldn't break anything that you do that depends on this behavior.

version(mir_test_date)
unittest
{
    auto x = YearMonth(2020, 1);
    auto x1 = x + 1;
    auto x2 = x + 2;
    auto x3 = x + 3;
    import std.stdio: writeln;
    writeln(x3); // prints YearMonth(2020, 7)
}

@9il
Copy link
Member

9il commented Jul 22, 2022

That is because opBinary bug. It should use a temporal variable instead. BTW, we have two implementation addMonth and add!months. For Date it is needed for the historical reasons. But for other types we can use only one of them. I would prefer to remove add! for other types because it can cause bugs.

@jmh530
Copy link
Contributor Author

jmh530 commented Jul 25, 2022

Closed in favor of PR #438

@jmh530 jmh530 closed this Jul 25, 2022
@jmh530 jmh530 deleted the DateIterator branch July 26, 2022 17:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants