Re: The difference between the dates in years

2024-02-10 Thread Brad Roberts via Digitalmars-d-learn

On 2/10/2024 6:01 PM, matheus via Digitalmars-d-learn wrote:

On Saturday, 10 February 2024 at 22:11:48 UTC, Brad Roberts wrote:
Back when I was doing lots of software developer interviews, one of my 
frequent questions involved date math.  This wasn't because it's 
difficult from a coding standpoint, but that it's NOT a coding 
problem. The key part of the question is realization that it's a 
requirements question.  The thing that makes dates complicated is 
defining what the question actually is.


The topic _seems_ like it should be simple, but the deeper you dig the 
more you realize it's anything but simple.




Interesting but I have a doubt, they (Interviewees) should do the test 
with already existing Date Functions of given language or write new ones?


Matheus.


My interviews were never tests, they were discussions that might also 
involve coding tasks.  In this case, the discussion was about 
requirements gathering disguised initially as a coding task.  By and 
large, I never put a lot of weight on the coding parts themselves and 
mostly focused on problem solving and thinking skills.  If the candidate 
couldn't get past writing code and wouldn't ask questions, that was a 
very bad sign.


Re: The difference between the dates in years

2024-02-10 Thread Steven Schveighoffer via Digitalmars-d-learn
On Saturday, 10 February 2024 at 15:53:09 UTC, Alexander Zhirov 
wrote:
Is it possible to calculate the difference between dates in 
years using regular means? Something like that



```
writeln(Date(1999, 3, 1).diffMonths(Date(1999, 1, 1)));
```

At the same time, keep in mind that the month and day matter, 
because the difference between the year, taking into account 
the month that has not come, will be less.


My abilities are not yet enough to figure it out more elegantly.


OK, so I thought this was already taking into account the day of 
the month.


This is what I came up with:

```d
int diffMonthNew(Date d1, Date d2)
{
auto diff = d1.diffMonths(d2);
if(diff > 0)
return diff + (d1.day < d2.day ? -1 : 0);
else if(diff < 0)
return diff + (d1.day > d2.day ? 1 : 0);
return 0;
}
```

Then if you want the years, it would be `diffMonthNew(d1, d2) / 
12`


-Steve


Re: The difference between the dates in years

2024-02-10 Thread Jonathan M Davis via Digitalmars-d-learn
On Saturday, February 10, 2024 7:31:47 PM MST Steven Schveighoffer via 
Digitalmars-d-learn wrote:
> On Saturday, 10 February 2024 at 23:48:56 UTC, Jonathan M Davis
>
> wrote:
> > If I understand correctly, he cares about how far into the
> > month the dates
> > are, whereas diffMonths ignores the smaller units, meaning that
> > you get the
> > same result no matter when in the month the dates are. So,
> > 2000-05-10 - 1990-05-09 would give 10, whereas 2000-05-10 -
> > 1990-05-30
> > would give 9. diffMonths / 12 would give 10 in both cases.
>
> I thought `diffMonths` was actually already taking this into
> account...
>
> Looking at the impl, it's pretty simple.
>
> Would it make sense to have an overload that takes into account
> the day as well as the month/year? This kind of stuff is
> sometimes tricky to get right.

Possibly. Given the trickiness involved, there probably should be a function
in std.datetime to handle it, but I'll have to think about what the best way
to do it would be in terms of the API.

It is kind of similar to how some functions behave differently depending on
how you want to treat the end of the month (e.g. whether adding a month to
May 31st gives you June 30th or July 1st), but it's also not quite the same.
So, the enum related to that wouldn't be appropriate, but it's yet another
edge case where sometimes you want one behavior, and at other times, you
want the other behavior.

- Jonathan M Davis





Re: The difference between the dates in years

2024-02-10 Thread Steven Schveighoffer via Digitalmars-d-learn
On Saturday, 10 February 2024 at 23:48:56 UTC, Jonathan M Davis 
wrote:


If I understand correctly, he cares about how far into the 
month the dates
are, whereas diffMonths ignores the smaller units, meaning that 
you get the

same result no matter when in the month the dates are. So,
2000-05-10 - 1990-05-09 would give 10, whereas 2000-05-10 - 
1990-05-30

would give 9. diffMonths / 12 would give 10 in both cases.


I thought `diffMonths` was actually already taking this into 
account...


Looking at the impl, it's pretty simple.

Would it make sense to have an overload that takes into account 
the day as well as the month/year? This kind of stuff is 
sometimes tricky to get right.


-Steve


Re: The difference between the dates in years

2024-02-10 Thread matheus via Digitalmars-d-learn

On Saturday, 10 February 2024 at 22:11:48 UTC, Brad Roberts wrote:
Back when I was doing lots of software developer interviews, 
one of my frequent questions involved date math.  This wasn't 
because it's difficult from a coding standpoint, but that it's 
NOT a coding problem. The key part of the question is 
realization that it's a requirements question.  The thing that 
makes dates complicated is defining what the question actually 
is.


The topic _seems_ like it should be simple, but the deeper you 
dig the more you realize it's anything but simple.




Interesting but I have a doubt, they (Interviewees) should do the 
test with already existing Date Functions of given language or 
write new ones?


Matheus.


Re: The difference between the dates in years

2024-02-10 Thread Jonathan M Davis via Digitalmars-d-learn
On Saturday, February 10, 2024 4:20:33 PM MST Steven Schveighoffer via 
Digitalmars-d-learn wrote:
> On Saturday, 10 February 2024 at 15:53:09 UTC, Alexander Zhirov
>
> wrote:
> > Is it possible to calculate the difference between dates in
> > years using regular means? Something like that
> >
> >
> > ```
> > writeln(Date(1999, 3, 1).diffMonths(Date(1999, 1, 1)));
> > ```
> >
> > At the same time, keep in mind that the month and day matter,
> > because the difference between the year, taking into account
> > the month that has not come, will be less.
> >
> > My abilities are not yet enough to figure it out more elegantly.
>
> Maybe I'm not understanding the question, but why not that result
> / 12?

If I understand correctly, he cares about how far into the month the dates
are, whereas diffMonths ignores the smaller units, meaning that you get the
same result no matter when in the month the dates are. So,
2000-05-10 - 1990-05-09 would give 10, whereas 2000-05-10 - 1990-05-30
would give 9. diffMonths / 12 would give 10 in both cases.

- Jonathan M Davis





Re: The difference between the dates in years

2024-02-10 Thread Steven Schveighoffer via Digitalmars-d-learn
On Saturday, 10 February 2024 at 15:53:09 UTC, Alexander Zhirov 
wrote:
Is it possible to calculate the difference between dates in 
years using regular means? Something like that



```
writeln(Date(1999, 3, 1).diffMonths(Date(1999, 1, 1)));
```

At the same time, keep in mind that the month and day matter, 
because the difference between the year, taking into account 
the month that has not come, will be less.


My abilities are not yet enough to figure it out more elegantly.


Maybe I'm not understanding the question, but why not that result 
/ 12?


-Steve


Re: The difference between the dates in years

2024-02-10 Thread Jonathan M Davis via Digitalmars-d-learn
On Saturday, February 10, 2024 3:11:48 PM MST Brad Roberts via Digitalmars-d-
learn wrote:
> Back when I was doing lots of software developer interviews, one of my
> frequent questions involved date math.  This wasn't because it's
> difficult from a coding standpoint, but that it's NOT a coding problem.
> The key part of the question is realization that it's a requirements
> question.  The thing that makes dates complicated is defining what the
> question actually is.
>
> The topic _seems_ like it should be simple, but the deeper you dig the
> more you realize it's anything but simple.

Indeed. And because it seems simple at first, it's very common for code to
be written which does the wrong thing with regards to dates and times -
often which seems like it does the right thing, because it works a lot of
the time, when in fact, there are edge cases where it definitely does the
wrong thing (e.g. with regards to leap years or DST). And math around months
is a prime area where it's difficult to get right in part because different
people have different requirements depending on the actual problem that
they're trying to solve.

- Jonathan M Davis





Re: The difference between the dates in years

2024-02-10 Thread Brad Roberts via Digitalmars-d-learn
Back when I was doing lots of software developer interviews, one of my 
frequent questions involved date math.  This wasn't because it's 
difficult from a coding standpoint, but that it's NOT a coding problem. 
The key part of the question is realization that it's a requirements 
question.  The thing that makes dates complicated is defining what the 
question actually is.


The topic _seems_ like it should be simple, but the deeper you dig the 
more you realize it's anything but simple.


On 2/10/2024 7:53 AM, Alexander Zhirov via Digitalmars-d-learn wrote:
Is it possible to calculate the difference between dates in years using 
regular means? Something like that



```
writeln(Date(1999, 3, 1).diffMonths(Date(1999, 1, 1)));
```

At the same time, keep in mind that the month and day matter, because 
the difference between the year, taking into account the month that has 
not come, will be less.


My abilities are not yet enough to figure it out more elegantly.


Re: The difference between the dates in years

2024-02-10 Thread Lance Bachmeier via Digitalmars-d-learn
On Saturday, 10 February 2024 at 21:56:30 UTC, Lance Bachmeier 
wrote:
On Saturday, 10 February 2024 at 15:53:09 UTC, Alexander Zhirov 
wrote:
Is it possible to calculate the difference between dates in 
years using regular means? Something like that



```
writeln(Date(1999, 3, 1).diffMonths(Date(1999, 1, 1)));
```

At the same time, keep in mind that the month and day matter, 
because the difference between the year, taking into account 
the month that has not come, will be less.


My abilities are not yet enough to figure it out more 
elegantly.


I'm assuming you mean you want the number of full years between 
the dates. If so, I use something like this:


```
import std;

void main() {
writeln(fullYears(Date(1999, 3, 1), Date(1999, 2, 1)));
writeln(fullYears(Date(2000, 3, 1), Date(1999, 2, 1)));
writeln(fullYears(Date(2000, 3, 1), Date(1999, 4, 1)));
writeln(fullYears(Date(2006, 4, 1), Date(1999, 4, 1)));
}

bool earlierInYear(Date date1, Date date2) {
return date1 < Date(date1.year, date2.month, date2.day);
}

long fullYears(Date date1, Date date2) {
assert(date1 >= date2, "The first date has to be later");
if (date1.earlierInYear(date2)) {
return max(date1.year - date2.year, 0);
} else {
return date1.year - date2.year;
}
}
```


should be

```
long fullYears(Date date1, Date date2) {
assert(date1 >= date2, "The first date has to be later");
if (date1.earlierInYear(date2)) {
return max(date1.year - date2.year - 1, 0);
} else {
return date1.year - date2.year;
}
}
```


Re: The difference between the dates in years

2024-02-10 Thread Lance Bachmeier via Digitalmars-d-learn
On Saturday, 10 February 2024 at 15:53:09 UTC, Alexander Zhirov 
wrote:
Is it possible to calculate the difference between dates in 
years using regular means? Something like that



```
writeln(Date(1999, 3, 1).diffMonths(Date(1999, 1, 1)));
```

At the same time, keep in mind that the month and day matter, 
because the difference between the year, taking into account 
the month that has not come, will be less.


My abilities are not yet enough to figure it out more elegantly.


I'm assuming you mean you want the number of full years between 
the dates. If so, I use something like this:


```
import std;

void main() {
writeln(fullYears(Date(1999, 3, 1), Date(1999, 2, 1)));
writeln(fullYears(Date(2000, 3, 1), Date(1999, 2, 1)));
writeln(fullYears(Date(2000, 3, 1), Date(1999, 4, 1)));
writeln(fullYears(Date(2006, 4, 1), Date(1999, 4, 1)));
}

bool earlierInYear(Date date1, Date date2) {
return date1 < Date(date1.year, date2.month, date2.day);
}

long fullYears(Date date1, Date date2) {
assert(date1 >= date2, "The first date has to be later");
if (date1.earlierInYear(date2)) {
return max(date1.year - date2.year, 0);
} else {
return date1.year - date2.year;
}
}
```


Re: The difference between the dates in years

2024-02-10 Thread Jonathan M Davis via Digitalmars-d-learn
On Saturday, February 10, 2024 8:53:09 AM MST Alexander Zhirov via 
Digitalmars-d-learn wrote:
> Is it possible to calculate the difference between dates in years
> using regular means? Something like that
>
>
> ```
> writeln(Date(1999, 3, 1).diffMonths(Date(1999, 1, 1)));
> ```
>
> At the same time, keep in mind that the month and day matter,
> because the difference between the year, taking into account the
> month that has not come, will be less.
>
> My abilities are not yet enough to figure it out more elegantly.

Well, diffMonths could be used to build what you want, but std.datetime
doesn't really provide a direct solution for it.

Subtracting one Date from another gives you a Duration, but that doesn't
take the month or year into account, because the lengths of the months are
variable.

diffMonths is the solution to get around that, since it does take the exact
years and months involved to give you the number of months. However, it
doesn't take the days of the month into account. It's just diffing the
months themselves, and any day of the month counts as being part of that
month.

However, after some mucking around, I think that I have a solution built on
top of diffMonths, though of course, it's possible that I screwed up
somewhere with my test dates. I named it yearsApart rather than diffYears,
since unlike diffMonths, it does take the smaller units into account. But of
course, you can name it whatever you want.

import std.datetime.date : Date;

int yearsApart(Date lhs, Date rhs)
{
auto months = lhs.diffMonths(rhs);
auto years = months / 12;

if(years == 0)
return 0;

auto remainder = months % 12;

if(remainder != 0)
return years;

if(months >= 0)
return lhs.day >= rhs.day ? years : years - 1;

return lhs.day <= rhs.day ? years : years + 1;
}

unittest
{
assert(yearsApart(Date(1999, 3, 1), Date(1999, 1, 1)) == 0);
assert(yearsApart(Date(1999, 1, 1), Date(1999, 3, 1)) == 0);

assert(yearsApart(Date(1999, 3, 1), Date(1998, 1, 1)) == 1);
assert(yearsApart(Date(1998, 3, 1), Date(1999, 1, 1)) == 0);

assert(yearsApart(Date(2000, 12, 1), Date(1995, 12, 1)) == 5);
assert(yearsApart(Date(1995, 12, 1), Date(2000, 12, 1)) == -5);

assert(yearsApart(Date(2000, 12, 2), Date(1995, 12, 1)) == 5);
assert(yearsApart(Date(1995, 12, 1), Date(2000, 12, 2)) == -5);

assert(yearsApart(Date(2000, 12, 1), Date(1995, 12, 2)) == 4);
assert(yearsApart(Date(1995, 12, 2), Date(2000, 12, 1)) == -4);

assert(yearsApart(Date(2000, 2, 29), Date(1999, 2, 28)) == 1);
assert(yearsApart(Date(1999, 2, 28), Date(2000, 2, 29)) == -1);

assert(yearsApart(Date(2000, 2, 29), Date(1999, 3, 1)) == 0);
assert(yearsApart(Date(1999, 3, 1), Date(2000, 2, 29)) == 0);

assert(yearsApart(Date(2000, 2, 29), Date(1998, 3, 1)) == 1);
assert(yearsApart(Date(1998, 3, 1), Date(2000, 2, 29)) == -1);

assert(yearsApart(Date(2001, 3, 1), Date(2000, 2, 29)) == 1);
assert(yearsApart(Date(2000, 2, 29), Date(2001, 3, 1)) == -1);

assert(yearsApart(Date(2005, 3, 1), Date(2000, 2, 29)) == 5);
assert(yearsApart(Date(2004, 3, 1), Date(2000, 2, 29)) == 4);
assert(yearsApart(Date(2003, 3, 1), Date(2000, 2, 29)) == 3);
assert(yearsApart(Date(2002, 3, 1), Date(2000, 2, 29)) == 2);
assert(yearsApart(Date(2001, 3, 1), Date(2000, 2, 29)) == 1);
assert(yearsApart(Date(2000, 3, 1), Date(2000, 2, 29)) == 0);

assert(yearsApart(Date(2000, 2, 29), Date(2001, 3, 1)) == -1);
assert(yearsApart(Date(2000, 2, 29), Date(2002, 3, 1)) == -2);
assert(yearsApart(Date(2000, 2, 29), Date(2003, 3, 1)) == -3);
assert(yearsApart(Date(2000, 2, 29), Date(2004, 3, 1)) == -4);
assert(yearsApart(Date(2000, 2, 29), Date(2005, 3, 1)) == -5);

assert(yearsApart(Date(2005, 2, 28), Date(2000, 2, 29)) == 4);
assert(yearsApart(Date(2004, 2, 29), Date(2000, 2, 29)) == 4);
assert(yearsApart(Date(2004, 2, 28), Date(2000, 2, 29)) == 3);
assert(yearsApart(Date(2003, 2, 28), Date(2000, 2, 29)) == 2);
assert(yearsApart(Date(2002, 2, 28), Date(2000, 2, 29)) == 1);
assert(yearsApart(Date(2001, 2, 28), Date(2000, 2, 29)) == 0);
assert(yearsApart(Date(2000, 2, 29), Date(2000, 2, 29)) == 0);
assert(yearsApart(Date(2000, 2, 28), Date(2000, 2, 29)) == 0);

assert(yearsApart(Date(2000, 2, 29), Date(2000, 2, 28)) == 0);
assert(yearsApart(Date(2000, 2, 29), Date(2000, 2, 29)) == 0);
assert(yearsApart(Date(2000, 2, 29), Date(2001, 2, 28)) == 0);
assert(yearsApart(Date(2000, 2, 29), Date(2002, 2, 28)) == -1);
assert(yearsApart(Date(2000, 2, 29), Date(2003, 2, 28)) == -2);
assert(yearsApart(Date(2000, 2, 29), Date(2004, 2, 28)) == -3);
assert(yearsApart(Date(2000, 2, 29), Date(2004, 2, 29)) == -4);
assert(yearsApart(Date(2000, 2, 29), Date(2005, 2, 28)) == -4);
}

- Jonathan M Davis





Re: The difference between the dates in years

2024-02-10 Thread matheus via Digitalmars-d-learn
On Saturday, 10 February 2024 at 19:16:35 UTC, Alexander Zhirov 
wrote:

...


Maybe this will help: I think if you will divide it can't be 365, 
but 365.242199.


About your code: I having tested fully, but I found a few 
problems and I wrote (Again without further tests) as below:


import std;

int getDiffYears(string date) {
auto currentDate = cast(Date)Clock.currTime();
auto startDate = Date.fromISOExtString(date);
auto currentDay = currentDate.dayOfYear;
auto startDay = startDate.dayOfYear;
auto currentMonth = currentDate.month;
auto startMonth = startDate.month;
auto diffDays = currentDate - startDate;
auto diffYears = diffDays.total!"days"().to!int / 365;
return currentMonth >= startMonth && currentDay >= startDay ? 
diffYears : diffYears - 1;

}

int getDiffYears2(string date) {
auto now  = cast(Date)Clock.currTime();
auto from = Date.fromISOExtString(date);
auto dy = now.year-from.year;
auto dm = (from.month-now.month);
auto dd = (dm == 0 && from.day>now.day);
return dy - 1 * (dm > 0 || dd);
}

void main(){
writeln("2001-02-09 is ", getDiffYears("2001-02-09"));
writeln("2001-02-10 is ", getDiffYears("2001-02-10"));
writeln("2001-02-11 is ", getDiffYears("2001-02-11"));
writeln("2001-03-01 is ", getDiffYears("2001-03-01"));
writeln("");
writeln("2001-02-09 is ", getDiffYears2("2001-02-09"));
writeln("2001-02-10 is ", getDiffYears2("2001-02-10"));
writeln("2001-02-11 is ", getDiffYears2("2001-02-11"));
writeln("2001-03-01 is ", getDiffYears2("2001-03-01"));
}

Output:

2001-02-09 is 23
2001-02-10 is 23
2001-02-11 is 22
2001-03-01 is 21

2001-02-09 is 23
2001-02-10 is 23
2001-02-11 is 22
2001-03-01 is 22

Matheus.


Re: The difference between the dates in years

2024-02-10 Thread Alexander Zhirov via Digitalmars-d-learn
On Saturday, 10 February 2024 at 18:12:07 UTC, Alexander Zhirov 
wrote:

On Saturday, 10 February 2024 at 16:03:32 UTC, H. S. Teoh wrote:
On Sat, Feb 10, 2024 at 03:53:09PM +, Alexander Zhirov via 
Digitalmars-d-learn wrote:
Is it possible to calculate the difference between dates in 
years using regular means? Something like that



```
writeln(Date(1999, 3, 1).diffMonths(Date(1999, 1, 1)));
```

At the same time, keep in mind that the month and day matter, 
because the difference between the year, taking into account 
the month that has not come, will be less.


My abilities are not yet enough to figure it out more 
elegantly.


IIRC you can just subtract two DateTime's to get a Duration 
that you can then convert into whatever units you want.  Only 
thing is, in this case conversion to months may not work 
because months don't have a fixed duration (they can vary from 
28 days to 31 days) so there is no "correct" way of computing 
it, you need to program it yourself according to the exact 
calculation you want.



T


I did it this way, but there will be an inaccuracy, since 
somewhere there may be 366 days, and somewhere 365


```
auto d = cast(Date)Clock.currTime() - 
Date.fromISOExtString("2001-02-01");

writeln(d.total!"days"().to!int / 365);
```


```
int getDiffYears(string date) {
auto currentDate = cast(Date)Clock.currTime();
auto startDate = Date.fromISOExtString(date);
auto currentDay = currentDate.dayOfYear;
auto startDay = startDate.dayOfYear;
auto currentMonth = currentDate.month;
auto startMonth = startDate.month;
auto diffDays = currentDate - startDate;
auto diffYears = diffDays.total!"days"().to!int / 365;

	return currentMonth >= startMonth && currentDay >= startDay ? 
diffYears : diffYears - 1;

}
```


Re: The difference between the dates in years

2024-02-10 Thread Alexander Zhirov via Digitalmars-d-learn

On Saturday, 10 February 2024 at 16:03:32 UTC, H. S. Teoh wrote:
On Sat, Feb 10, 2024 at 03:53:09PM +, Alexander Zhirov via 
Digitalmars-d-learn wrote:
Is it possible to calculate the difference between dates in 
years using regular means? Something like that



```
writeln(Date(1999, 3, 1).diffMonths(Date(1999, 1, 1)));
```

At the same time, keep in mind that the month and day matter, 
because the difference between the year, taking into account 
the month that has not come, will be less.


My abilities are not yet enough to figure it out more 
elegantly.


IIRC you can just subtract two DateTime's to get a Duration 
that you can then convert into whatever units you want.  Only 
thing is, in this case conversion to months may not work 
because months don't have a fixed duration (they can vary from 
28 days to 31 days) so there is no "correct" way of computing 
it, you need to program it yourself according to the exact 
calculation you want.



T


I did it this way, but there will be an inaccuracy, since 
somewhere there may be 366 days, and somewhere 365


```
auto d = cast(Date)Clock.currTime() - 
Date.fromISOExtString("2001-02-01");

writeln(d.total!"days"().to!int / 365);
```


Re: The difference between the dates in years

2024-02-10 Thread H. S. Teoh via Digitalmars-d-learn
On Sat, Feb 10, 2024 at 03:53:09PM +, Alexander Zhirov via 
Digitalmars-d-learn wrote:
> Is it possible to calculate the difference between dates in years
> using regular means? Something like that
> 
> 
> ```
> writeln(Date(1999, 3, 1).diffMonths(Date(1999, 1, 1)));
> ```
> 
> At the same time, keep in mind that the month and day matter, because
> the difference between the year, taking into account the month that
> has not come, will be less.
> 
> My abilities are not yet enough to figure it out more elegantly.

IIRC you can just subtract two DateTime's to get a Duration that you can
then convert into whatever units you want.  Only thing is, in this case
conversion to months may not work because months don't have a fixed
duration (they can vary from 28 days to 31 days) so there is no
"correct" way of computing it, you need to program it yourself according
to the exact calculation you want.


T

-- 
PNP = Plug 'N' Pray


The difference between the dates in years

2024-02-10 Thread Alexander Zhirov via Digitalmars-d-learn
Is it possible to calculate the difference between dates in years 
using regular means? Something like that



```
writeln(Date(1999, 3, 1).diffMonths(Date(1999, 1, 1)));
```

At the same time, keep in mind that the month and day matter, 
because the difference between the year, taking into account the 
month that has not come, will be less.


My abilities are not yet enough to figure it out more elegantly.