Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Difference of days in terms of Year, Month Week and Day

Status
Not open for further replies.

santanudas

Technical User
Mar 18, 2002
121
GB
Greetings all,

As said in the subject line, trying to write a script to print the number of years, months weeks and days between two given dates. Does anyone know how to do that?

So far I've tried Date::Calc module, which returns the difference as number of days but then I'm stuck converting it into years, months, weeks and day form. Any help highly appreciated. Thanks in advance. cheers!!!
 
Trouble is, how long is a month? 28? 29? 30? 31 days? Even a year: 365 or 366 days? Weeks and days is the best you can reliably do, as far as I can see.
 
Yes, that's the actual problem, I think. But there must be some way of doing that. I'll utterly surprised if anyone else hasn't tried this before. Cheers!!!
 
Hi,

In order for Date::Calc to have accurately calculated the number of days between 2 dates then it must have known how long each month/year it processed is, therefore I assume that the module must be capable of fufilling your task. I have been trying to figure this one out for the last hour but haven't come up with much. However I was able to find a rough solution using the DateTime module which may be of help to you,
Chris
 
While you were going through the docs of Date::Calc, did you take a look at Delta_YMD? Did it not work for you?
Code:
[url=http://perldoc.perl.org/functions/use.html][black][b]use[/b][/black][/url] [green]Date::Calc[/green] [red]qw/[/red][purple]Delta_YMD Delta_Days[/purple][red]/[/red][red];[/red]

[url=http://perldoc.perl.org/functions/my.html][black][b]my[/b][/black][/url] [red]([/red][blue]$y1[/blue], [blue]$m1[/blue], [blue]$d1[/blue][red])[/red] = [red]([/red][fuchsia]2008[/fuchsia], [fuchsia]1[/fuchsia], [fuchsia]1[/fuchsia][red])[/red][red];[/red]
[black][b]my[/b][/black] [red]([/red][blue]$y2[/blue], [blue]$m2[/blue], [blue]$d2[/blue][red])[/red] = [red]([/red][fuchsia]2009[/fuchsia], [fuchsia]2[/fuchsia], [fuchsia]15[/fuchsia][red])[/red][red];[/red]
[black][b]my[/b][/black] [red]([/red][blue]$dy[/blue], [blue]$dm[/blue], [blue]$dd[/blue][red])[/red] = [maroon]Delta_YMD[/maroon][red]([/red][blue]$y1[/blue], [blue]$m1[/blue], [blue]$d1[/blue],[blue]$y2[/blue], [blue]$m2[/blue], [blue]$d2[/blue][red])[/red][red];[/red]

[url=http://perldoc.perl.org/functions/print.html][black][b]print[/b][/black][/url] [red]"[/red][purple]Date 1: [blue]$y1[/blue]-[blue]$m1[/blue]-[blue]$d1[/blue][purple][b]\n[/b][/purple]Date 2: [blue]$y2[/blue]-[blue]$m2[/blue]-[blue]$d2[/blue][purple][b]\n[/b][/purple][/purple][red]"[/red][red];[/red]
[black][b]print[/b][/black] [red]"[/red][purple]Delta Days: [/purple][red]"[/red] . [maroon]Delta_Days[/maroon][red]([/red][blue]$y1[/blue], [blue]$m1[/blue], [blue]$d1[/blue],[blue]$y2[/blue], [blue]$m2[/blue], [blue]$d2[/blue][red])[/red] . [red]"[/red][purple][purple][b]\n[/b][/purple][/purple][red]"[/red][red];[/red]
[black][b]print[/b][/black] [red]"[/red][purple]Years: [blue]$dy[/blue], Months: [blue]$dm[/blue], Days: [blue]$dd[/blue][purple][b]\n[/b][/purple][/purple][red]"[/red][red];[/red]
 
Trouble is, how long is a month? 28? 29? 30? 31 days? Even a year: 365 or 366 days? Weeks and days is the best you can reliably do, as far as I can see

Thats only relevent if you are calculating the total number of days between two dates. Which is not the case here.

You can use simple math to determine the span between dates given the start and end date in YYYY MM DD format. It does not matter how many days are in each month or year, for example:

Jan to June (1 to 6) there is 5 months difference. Add the days:

Jan 12 to June 29 there is 5 months and 17 days difference. Add in the years and calculation is still the same.

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
The only slightly tricky part would be if you wanted to add the name of the day in the week to the start/end dates and the final calculation. But you could just use Time::Local to determine the day of the week instead of a Date module, but using the Date module is good if you are doing other date calculations as it is a single interace to all your date needs.

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Thank you guys for your time helping me out; I really appreciate it.

Zhris:
If I copy your code exactly as it is and run I get this error:

Name "main::DATA" used only once: possible typo at ./test_a.pl line 9.
readline() on unopened filehandle DATA at ./test_a.pl line 9.
Can't call method "delta_md" on an undefined value at ./test_a.pl line 10.
Any idea what am I missing?


rharsh:
I didn't try Delta_YMD before but when I try out your code, I get rather funny result. The difference between 31st October 2008 and 16th January 2009 comes as:

Date 1: 2008-10-31
Date 2: 2009-1-16
Delta Days: 77
Years: 1, Months: -9, Days: -15
Looks like it just doing simple subtract: Year($y2 - $y1), Month($m2 - $m1), Day($d2 - $d1)

Cheers!!!

 
The output is correct, and is documented in the module to be precisely what you are getting. It even shows that in the documentation:

($Dy,$Dm,$Dd) = Delta_YMD($year1,$month1,$day1, $year2,$month2,$day2);

This function returns the vector
( $year2 - $year1, $month2 - $month1, $day2 - $day1 )

What were you expecting?

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
I was only expecting the correct result in standard "human understandable form" - the difference between 2008/10/31 and 2009/1/16 - in this case it isn't. Who says like: "You are 1 year, -9 months and -15 days old" or "It's been 1 year, -9 months and -15 days since we talked"? cheers!!!
 
Hi santanudas,

But it cannot be a big problem to correct the returned results into "human understandable form" - something like this:
Code:
[COLOR=#804040][b]use [/b][/color]Date::Calc [COLOR=#ff00ff]qw/[/color][COLOR=#ff00ff]Delta_YMD Delta_Days Days_in_Month[/color][COLOR=#ff00ff]/[/color];

[COLOR=#804040][b]my[/b][/color] ([COLOR=#008080]$y1[/color], [COLOR=#008080]$m1[/color], [COLOR=#008080]$d1[/color]) = ([COLOR=#ff00ff]2008[/color], [COLOR=#ff00ff]10[/color], [COLOR=#ff00ff]31[/color]);
[COLOR=#804040][b]my[/b][/color] ([COLOR=#008080]$y2[/color], [COLOR=#008080]$m2[/color], [COLOR=#008080]$d2[/color]) = ([COLOR=#ff00ff]2009[/color], [COLOR=#ff00ff]1[/color], [COLOR=#ff00ff]16[/color]);
[COLOR=#804040][b]my[/b][/color] ([COLOR=#008080]$dy[/color], [COLOR=#008080]$dm[/color], [COLOR=#008080]$dd[/color]) = Delta_YMD([COLOR=#008080]$y1[/color], [COLOR=#008080]$m1[/color], [COLOR=#008080]$d1[/color],[COLOR=#008080]$y2[/color], [COLOR=#008080]$m2[/color], [COLOR=#008080]$d2[/color]);

[COLOR=#804040][b]print[/b][/color] [COLOR=#ff00ff]"[/color][COLOR=#ff00ff]Date 1: [/color][COLOR=#008080]$y1[/color][COLOR=#ff00ff]-[/color][COLOR=#008080]$m1[/color][COLOR=#ff00ff]-[/color][COLOR=#008080]$d1[/color][COLOR=#6a5acd]\n[/color][COLOR=#ff00ff]Date 2: [/color][COLOR=#008080]$y2[/color][COLOR=#ff00ff]-[/color][COLOR=#008080]$m2[/color][COLOR=#ff00ff]-[/color][COLOR=#008080]$d2[/color][COLOR=#6a5acd]\n[/color][COLOR=#ff00ff]"[/color];
[COLOR=#804040][b]print[/b][/color] [COLOR=#ff00ff]"[/color][COLOR=#ff00ff]Delta Days: [/color][COLOR=#ff00ff]"[/color] . Delta_Days([COLOR=#008080]$y1[/color], [COLOR=#008080]$m1[/color], [COLOR=#008080]$d1[/color],[COLOR=#008080]$y2[/color], [COLOR=#008080]$m2[/color], [COLOR=#008080]$d2[/color]) . [COLOR=#ff00ff]"[/color][COLOR=#6a5acd]\n[/color][COLOR=#ff00ff]"[/color];
[COLOR=#804040][b]print[/b][/color] [COLOR=#ff00ff]"[/color][COLOR=#ff00ff]Years: [/color][COLOR=#008080]$dy[/color][COLOR=#ff00ff], Months: [/color][COLOR=#008080]$dm[/color][COLOR=#ff00ff], Days: [/color][COLOR=#008080]$dd[/color][COLOR=#6a5acd]\n[/color][COLOR=#ff00ff]"[/color];

([COLOR=#008080]$dy[/color], [COLOR=#008080]$dm[/color], [COLOR=#008080]$dd[/color])=[COLOR=#008080]&DeltaYMD_HUF[/color]([COLOR=#008080]$y1[/color], [COLOR=#008080]$m1[/color], [COLOR=#008080]$d1[/color], [COLOR=#008080]$y2[/color], [COLOR=#008080]$m2[/color], [COLOR=#008080]$d2[/color], [COLOR=#008080]$dy[/color], [COLOR=#008080]$dm[/color], [COLOR=#008080]$dd[/color]);
[COLOR=#804040][b]print[/b][/color] [COLOR=#ff00ff]"[/color][COLOR=#ff00ff]Now in Human Understandable Form:[/color][COLOR=#6a5acd]\n[/color][COLOR=#ff00ff]"[/color];
[COLOR=#804040][b]print[/b][/color] [COLOR=#ff00ff]"[/color][COLOR=#ff00ff]Years: [/color][COLOR=#008080]$dy[/color][COLOR=#ff00ff], Months: [/color][COLOR=#008080]$dm[/color][COLOR=#ff00ff], Days: [/color][COLOR=#008080]$dd[/color][COLOR=#6a5acd]\n[/color][COLOR=#ff00ff]"[/color];

[COLOR=#0000ff]###[/color]
[COLOR=#804040][b]sub[/b][/color][COLOR=#008080] [/color][COLOR=#008080]DeltaYMD_HUF[/color]{
  [COLOR=#0000ff]# correct date differences returned from Delta_YMD [/color]
  [COLOR=#0000ff]# into human understandable form [/color]
  [COLOR=#804040][b]my[/b][/color] ([COLOR=#008080]$y1[/color], [COLOR=#008080]$m1[/color], [COLOR=#008080]$d1[/color], [COLOR=#008080]$y2[/color], [COLOR=#008080]$m2[/color], [COLOR=#008080]$d2[/color], [COLOR=#008080]$dy[/color], [COLOR=#008080]$dm[/color], [COLOR=#008080]$dd[/color]) = [COLOR=#008080]@_[/color];
  [COLOR=#804040][b]if[/b][/color] ([COLOR=#008080]$dd[/color] < [COLOR=#ff00ff]0[/color]){
    [COLOR=#0000ff]# correct number of days and months[/color]
    [COLOR=#008080]$dd[/color] = Days_in_Month([COLOR=#008080]$y2[/color], [COLOR=#008080]$m2[/color]) - [COLOR=#804040][b]abs[/b][/color]([COLOR=#008080]$dd[/color]);
    [COLOR=#008080]$dm[/color] -= [COLOR=#ff00ff]1[/color];
  }
  [COLOR=#804040][b]if[/b][/color] ([COLOR=#008080]$dm[/color] < [COLOR=#ff00ff]0[/color]){
    [COLOR=#0000ff]# correct number of months and years[/color]
    [COLOR=#008080]$dm[/color] = [COLOR=#ff00ff]12[/color] - [COLOR=#804040][b]abs[/b][/color]([COLOR=#008080]$dm[/color]);
    [COLOR=#008080]$dy[/color] -= [COLOR=#ff00ff]1[/color];
  }
  [COLOR=#804040][b]return[/b][/color]([COLOR=#008080]$dy[/color], [COLOR=#008080]$dm[/color], [COLOR=#008080]$dd[/color])
}

Output
Code:
Date 1: 2008-10-31
Date 2: 2009-1-16
Delta Days: 77
[COLOR=red]Years: 1, Months: -9, Days: -15[/color]
Now in Human Understandable Form:
[COLOR=green]Years: 0, Months: 2, Days: 16[/color]
 
Here it is taken directly from the documentation:

Code:
#!perl
  use strict;
  use Date::Calc qw(Today Delta_YMD Add_Delta_YM Delta_Days Date_to_Text);

  my($sign,$delta);
  my $today = [2008,10,31];
  my $target = [2009,1,16];

  if (Delta_Days(@$today,@$target) < 0)
  {
      $sign = "since";
      $delta = Normalize_Delta_YMD($target,$today);
  }
  else
  {
      $sign = "until";
      $delta = Normalize_Delta_YMD($today,$target);
  }
  print "Today is ", Date_to_Text(@$today), "\n";
  printf
  (
      "%d year%s, %d month%s, %d day%s %s %s\n",
      $delta->[0], (($delta->[0]==1)?'':'s'),
      $delta->[1], (($delta->[1]==1)?'':'s'),
      $delta->[2], (($delta->[2]==1)?'':'s'),
      $sign,
      Date_to_Text(@$target)
  );

  sub Normalize_Delta_YMD
  {
      my($date1,$date2) = @_;
      my(@delta);

      @delta = Delta_YMD(@$date1,@$date2);
      while ($delta[1] < 0 or $delta[2] < 0)
      {
          if ($delta[1] < 0) { $delta[0]--; $delta[1] += 12; }
          if ($delta[2] < 0)
          {
              $delta[1]--;
              $delta[2] = Delta_Days(Add_Delta_YM(@$date1,@delta[0,1]),@$date2);
          }
      }
      return \@delta;
  }

As people often say: RTFM

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Ok, I saw it in doc now. But when they have the function Normalize_Delta_YMD in doc as a recipe no.17, it's probably one of the common tasks what people need to do.
Then I don't understand why this function is not a part of the module Date::Calc, when it is now in version 5.4.
:)
 
Many thanks mikrom and Kevin for your time. I tried both - both are working but returning different result. I was trying many different dates and I found the difference dates - 2008/10/31 and 2008/11/4 is reported by mikrom's script is: 3
Date 1: 2008-10-31
Date 2: 2008-11-4
Delta Days: 4
Unformatted => Years: 0, Months: 1, Days: -27
Now in Human Understandable Form:
Years: 0, Months: 0, Days: 3
and with the same date, Kevin's script reports: 4
Today is Fri 31-Oct-2008
0 years, 0 months, 4 days until Tue 4-Nov-2008
Isn't 4-days the correct answer? Cheers!!!
 
The script is not mine, its copied right out of the Date::Calc documentation. Have you looked over the modules documentation?

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Hi santanudas,

Take rather the function from module documentation posted by Kevin. What I posted was only quick example, that such a correction is possible, but it was not tested.
 
santanudas, as for any programming task, even the simplest one, you need to first define the rules.
In your question the following points are unclear:
-I suppose of course that the two dates should first be put in increasing order
-another prerequisite is whether you consider the second date inclusive (so that the difference of two consecutive days would be 2 days) or exclusive (in other words: both dates calculated at 00:00 in the morning), so that the difference would be 1 day
-concerning the difference in years I understand from you that you consider the difference equal to zero, of course, when the two dates are in the same calendar year, but also when they are in two consecutive years: this means that the difference in days that makes the balance may well by higher than 365 days. Correct?
-a similar argument applies to the months and the weeks: zero would mean that the two dates are either in the same month or week, or that they are in two consecutive periods (BTW you should also define what is the starting day for the week, as there is no standard for that)
-notice also that the difference in weeks need be a separate item, as the weeks do not integrally divide the months, of course
-if the above is correct, how to interpret the difference in days becomes more difficult. Take as an example Feb 1st and April 30: if the intervening number of day needs to be interpreted as the balance with respect to the difference in months, in that case you would have a difference of 1 month (March) plus 28 days in February and 29 (or 30: see above) day in April, for a total difference in days 58 or 59.
Please come back with a bunch of examples that would fully clarify your rules, if you still need help.

Franco
: Online engineering calculations
: Magnetic brakes for fun rides
: Air bearing pads
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top