Jump to page: 1 2
Thread overview
Convert duration to years?
Jan 15, 2017
Nestor
Jan 15, 2017
Dave Chapman
Jan 15, 2017
Nestor
Jan 15, 2017
ag0aep6g
Jan 15, 2017
rikki cattermole
Jan 15, 2017
Nestor
Jan 15, 2017
Nestor
Jan 15, 2017
rikki cattermole
Jan 15, 2017
biozic
Jan 15, 2017
Nestor
Jan 15, 2017
Nestor
Jan 15, 2017
biozic
Jan 15, 2017
Nestor
Jan 15, 2017
Jonathan M Davis
Jan 15, 2017
Nestor
January 15, 2017
Hi,

I would simply like to get someone's age, but I am a little lost with time and date functions. I can already get the duration, but after reading the documentation it's unclear to me how to convert that into years. See following code:

import std.stdio;

void getAge(int yyyy, int mm, int dd) {
  import std.datetime;
  SysTime t1 = SysTime(Date(yyyy, mm, dd));
  SysTime t2 = Clock.currTime();
  writeln(t2 - t1);
}

int main() {
  try
    getAge(1980, 1, 1);
  catch(Exception e) {
    writefln("%s.\n(%s, line %s)", e.msg, e.file, e.line);
  }
}

Notice getAge should return ubyte instead of void, only I haven't been able to find how to do it. Any suggestion would be welcome.

Thanks in advance.
January 15, 2017
On Sunday, 15 January 2017 at 03:43:32 UTC, Nestor wrote:
> Hi,
>
> I would simply like to get someone's age, but I am a little lost with time and date functions. I can already get the duration, but after reading the documentation it's unclear to me how to convert that into years. See following code:
>
> import std.stdio;
>
> void getAge(int yyyy, int mm, int dd) {
>   import std.datetime;
>   SysTime t1 = SysTime(Date(yyyy, mm, dd));
>   SysTime t2 = Clock.currTime();
>   writeln(t2 - t1);
> }
>
> int main() {
>   try
>     getAge(1980, 1, 1);
>   catch(Exception e) {
>     writefln("%s.\n(%s, line %s)", e.msg, e.file, e.line);
>   }
> }
>
> Notice getAge should return ubyte instead of void, only I haven't been able to find how to do it. Any suggestion would be welcome.
>
> Thanks in advance.

Does this do what you want?
import std.stdio;

uint getAge(int yyyy, int mm, int dd) {
  import std.datetime;
  SysTime t1 = SysTime(Date(yyyy, mm, dd));
  SysTime t2 = Clock.currTime();
  return( (t2.year - t1.year));
}

void main() {
  auto age = getAge(1980, 1, 1);
  writefln("age is %s", age);
}

January 15, 2017
On Sunday, 15 January 2017 at 06:23:56 UTC, Dave Chapman wrote:
> Does this do what you want?
> import std.stdio;
>
> uint getAge(int yyyy, int mm, int dd) {
>   import std.datetime;
>   SysTime t1 = SysTime(Date(yyyy, mm, dd));
>   SysTime t2 = Clock.currTime();
>   return( (t2.year - t1.year));
> }
>
> void main() {
>   auto age = getAge(1980, 1, 1);
>   writefln("age is %s", age);
> }

It seems to work, but not very accurately, see variation:

import std.stdio;

uint getAge() {
  import std.datetime;
  SysTime t1 = SysTime(Date(2000, 12, 31));
  SysTime t2 = SysTime(Date(2001, 1, 1));
  return((t2.year - t1.year));
}

void main() {
  auto age = getAge();
  writefln("age is %s", age);
}


I eventually came up with this, but it seems an ugly hack:

import std.stdio;

uint getAge(int yyyy, ubyte mm, ubyte dd) {
  ubyte correction;
  import std.datetime;
  SysTime t = Clock.currTime();
  if (t.month < mm) correction = 1;
  else if (t.month == mm) correction = (t.day < dd) ? 1 : 0;
  else correction = 0;
  return (t.year - yyyy - correction);
}

void main() {
  try
    writefln("Edad: %s años.", getAge(1958, 1, 21));
  catch(Exception e) {
    writefln("%s.\n(%s, line %s)", e.msg, e.file, e.line);
  }
}

Isn't there a built-in function to do this?
January 15, 2017
On 15/01/2017 4:43 PM, Nestor wrote:
> Hi,
>
> I would simply like to get someone's age, but I am a little lost with
> time and date functions. I can already get the duration, but after
> reading the documentation it's unclear to me how to convert that into
> years. See following code:
>
> import std.stdio;
>
> void getAge(int yyyy, int mm, int dd) {
>   import std.datetime;
>   SysTime t1 = SysTime(Date(yyyy, mm, dd));
>   SysTime t2 = Clock.currTime();
>   writeln(t2 - t1);
> }
>
> int main() {
>   try
>     getAge(1980, 1, 1);
>   catch(Exception e) {
>     writefln("%s.\n(%s, line %s)", e.msg, e.file, e.line);
>   }
> }
>
> Notice getAge should return ubyte instead of void, only I haven't been
> able to find how to do it. Any suggestion would be welcome.
>
> Thanks in advance.

So I had a go at this and found I struggled looking at "magic" functions and methods.
Turns out there is a much simpler answer.

int getAge(int yyyy, int mm, int dd) {
  import std.datetime;
  auto t1 = cast(DateTime)SysTime(Date(yyyy, mm, dd));
  auto t2 = cast(DateTime)Clock.currTime();

  int numYears;
  while(t2 > t1) {
     t1.add!"years"(1);
     numYears++;
  }

  return numYears;
}

January 15, 2017
On Sunday, 15 January 2017 at 07:25:26 UTC, rikki cattermole wrote:
> So I had a go at this and found I struggled looking at "magic" functions and methods.
> Turns out there is a much simpler answer.
>
> int getAge(int yyyy, int mm, int dd) {
>   import std.datetime;
>   auto t1 = cast(DateTime)SysTime(Date(yyyy, mm, dd));
>   auto t2 = cast(DateTime)Clock.currTime();
>
>   int numYears;
>   while(t2 > t1) {
>      t1.add!"years"(1);
>      numYears++;
>   }
>
>   return numYears;
> }


Well... correct me if I am wrong, but isn't t1.add!"years"(1) simply adding one year to t1?
January 15, 2017
I cleaned up the function a little, but it still feels like a hack:

uint getAge(uint yyyy, uint mm, uint dd) {
  import std.datetime;
  SysTime t = Clock.currTime;
  ubyte correction = 0;
  if(
    (t.month < mm) ||
    ( (t.month == mm) && (t.day < dd) )
  ) correction += 1;
  return (t.year - yyyy - correction);
}

Isn't there anything better?
January 15, 2017
On 15/01/2017 9:40 PM, Nestor wrote:
> I cleaned up the function a little, but it still feels like a hack:
>
> uint getAge(uint yyyy, uint mm, uint dd) {
>   import std.datetime;
>   SysTime t = Clock.currTime;
>   ubyte correction = 0;
>   if(
>     (t.month < mm) ||
>     ( (t.month == mm) && (t.day < dd) )
>   ) correction += 1;
>   return (t.year - yyyy - correction);
> }
>
> Isn't there anything better?

The problem with this is that it won't take into account leap years.
January 15, 2017
On Sunday, 15 January 2017 at 08:40:37 UTC, Nestor wrote:
> I cleaned up the function a little, but it still feels like a hack:
>
> uint getAge(uint yyyy, uint mm, uint dd) {
>   import std.datetime;
>   SysTime t = Clock.currTime;
>   ubyte correction = 0;
>   if(
>     (t.month < mm) ||
>     ( (t.month == mm) && (t.day < dd) )
>   ) correction += 1;
>   return (t.year - yyyy - correction);
> }
>
> Isn't there anything better?

It doesn't feel like a hack to me, because it's simple and correct code that comply with the common definition of a person's age. The only inaccuracy I can think of is about people born on February 29th...

January 15, 2017
On 01/15/2017 07:58 AM, Nestor wrote:
> I eventually came up with this, but it seems an ugly hack:
>
> import std.stdio;
>
> uint getAge(int yyyy, ubyte mm, ubyte dd) {
>   ubyte correction;
>   import std.datetime;
>   SysTime t = Clock.currTime();
>   if (t.month < mm) correction = 1;
>   else if (t.month == mm) correction = (t.day < dd) ? 1 : 0;
>   else correction = 0;
>   return (t.year - yyyy - correction);
> }
>
> void main() {
>   try
>     writefln("Edad: %s años.", getAge(1958, 1, 21));
>   catch(Exception e) {
>     writefln("%s.\n(%s, line %s)", e.msg, e.file, e.line);
>   }
> }

That's the better approach, I think. Years have variable lengths. Determining "age" in years works by comparing dates, not durations.

I would write it like this, but as far as I see yours does the same thing:

----
int getAge(int yyyy, int mm, int dd)
{
    import std.datetime;

    immutable SysTime now = Clock.currTime();
    immutable int years = now.year - yyyy;

    return mm > now.month || mm == now.month && dd > now.day
        ? years - 1 // birthday hasn't come yet this year
        : years; // birthday has already been this year
}

void main()
{
    import std.stdio;

    /* Day of writing: 2017-01-15 */
    writeln(getAge(1980, 1, 1)); /* 37 */
    writeln(getAge(1980, 1, 15)); /* 37 (birthday is today) */
    writeln(getAge(1980, 1, 30)); /* 36 */
    writeln(getAge(1980, 6, 1)); /* 36 */
}
----

> Isn't there a built-in function to do this?

If there is, finding it in std.datetime would take me longer than writing it myself.
January 15, 2017
On Sunday, 15 January 2017 at 11:01:28 UTC, biozic wrote:
> On Sunday, 15 January 2017 at 08:40:37 UTC, Nestor wrote:
>> I cleaned up the function a little, but it still feels like a hack:
>>
>> uint getAge(uint yyyy, uint mm, uint dd) {
>>   import std.datetime;
>>   SysTime t = Clock.currTime;
>>   ubyte correction = 0;
>>   if(
>>     (t.month < mm) ||
>>     ( (t.month == mm) && (t.day < dd) )
>>   ) correction += 1;
>>   return (t.year - yyyy - correction);
>> }
>>
>> Isn't there anything better?
>
> It doesn't feel like a hack to me, because it's simple and correct code that comply with the common definition of a person's age. The only inaccuracy I can think of is about people born on February 29th...

I know. I thought about it as well, but it's not something you can deal with cleanly.

For example, take a baby born in february 29 of year 2000 (leap year). In february 28 of 2001 that baby was one day short to one year.

Family can make a concession and celebrate birthdays in february 28 of non-leap years, but march 1 is the actual day when the year of life completes. Which one to choose?

Another way to deal with this is modifying the function to take a parameter which allows to do a relaxed calculation in non-leap years if one so desires.
« First   ‹ Prev
1 2