how many days ago is 2003-07-20 ?

M

Marcus

Can someone pls show the most solid way in perl to retrieve the number
of days ago a specific date string was?

Input: 2003-07-20
Output: 395

Thanks
M
 
G

Gunnar Hjalmarsson

Marcus said:
Can someone pls show the most solid way in perl to retrieve the
number of days ago a specific date string was?

Input: 2003-07-20
Output: 395

What have you tried? Personally I'd probably use Time::Local, which
would require a couple of extra lines of code, while others would use
e.g. Date::Calc.
 
Z

Zebee Johnstone

In comp.lang.perl.misc on 27 Aug 2004 16:35:04 -0700
Marcus said:
Can someone pls show the most solid way in perl to retrieve the number
of days ago a specific date string was?

Input: 2003-07-20
Output: 395

Date::Manip is one way.

4. The amount of time between two dates.

$date1=&ParseDate($string1);
$date2=&ParseDate($string2);
$delta=&DateCalc($date1,$date2,\$err);
=> 0:0:WK:DD:HH:MM:SS the weeks, days, hours, minutes,
and seconds between the two
$delta=&DateCalc($date1,$date2,\$err,1);
=> YY:MM:WK:DD:HH:MM:SS the years, months, etc. between
the two

There are other Date modules, that's just the one I've been using
because I handle dates in all sorts of weird formats and do all sorts of
weird thigns with them, it handles everything so far.

Zebee
 
A

Anno Siegel

Gunnar Hjalmarsson said:
What have you tried? Personally I'd probably use Time::Local, which
would require a couple of extra lines of code, while others would use
e.g. Date::Calc.

Do you have a simple, water-tight solution using only Time::Local?
Note that in the presence of DST a day may have more or less than 24
hours.

Anno
 
G

Gunnar Hjalmarsson

Anno said:
Do you have a simple, water-tight solution using only Time::Local?

Think so.

sub daysago {
shift =~ /^(\d{4})-(\d{2})-(\d{2})$/
or die "Invalid date format";
require Time::Local;
import Time::Local 'timelocal';
my $diff = timelocal(0,0,0,(localtime $^T)[3..5])
- timelocal(0,0,0,$3,$2-1,$1-1900);
$diff >= 0 or die "Future date not allowed";
sprintf '%.0f', $diff / 86400
}

print daysago('2003-07-20'), "\n";
Note that in the presence of DST a day may have more or less than
24 hours.

Doesn't the above sub take care of that?
 
A

Anno Siegel

Gunnar Hjalmarsson said:
Anno said:
Do you have a simple, water-tight solution using only Time::Local?

Think so.

sub daysago {
shift =~ /^(\d{4})-(\d{2})-(\d{2})$/
or die "Invalid date format";
require Time::Local;
import Time::Local 'timelocal';
my $diff = timelocal(0,0,0,(localtime $^T)[3..5])
- timelocal(0,0,0,$3,$2-1,$1-1900);
$diff >= 0 or die "Future date not allowed";
sprintf '%.0f', $diff / 86400
}

print daysago('2003-07-20'), "\n";
Note that in the presence of DST a day may have more or less than
24 hours.

Doesn't the above sub take care of that?

I don't know, but it is only obviously correct if the interval between
the two times is a multiple of 24 hours. Since that isn't always so,
I'd prefer a solution that has been checked for these cases instead of
checking myself.

Anno
 
G

Gunnar Hjalmarsson

Anno said:
Gunnar said:
Anno said:
Do you have a simple, water-tight solution using only
Time::Local?

Think so.

sub daysago {
shift =~ /^(\d{4})-(\d{2})-(\d{2})$/
or die "Invalid date format";
require Time::Local;
import Time::Local 'timelocal';
my $diff = timelocal(0,0,0,(localtime $^T)[3..5])
- timelocal(0,0,0,$3,$2-1,$1-1900);
$diff >= 0 or die "Future date not allowed";
sprintf '%.0f', $diff / 86400
}

print daysago('2003-07-20'), "\n";
Note that in the presence of DST a day may have more or less
than 24 hours.

Doesn't the above sub take care of that?

I don't know, but it is only obviously correct if the interval
between the two times is a multiple of 24 hours.

Hey, how is your math? ;-) We know it may differ 1/24 day, and since
that it far less than 1/2, to me it's pretty obvious that sprintf()
makes it return the correct number of days.
Since that isn't always so, I'd prefer a solution that has been
checked for these cases instead of checking myself.

Sometimes I feel that there is something religious about the faith in
using oversized modules. :(
 
A

Anno Siegel

Gunnar Hjalmarsson said:
Anno said:
Gunnar said:
Anno Siegel wrote:
Do you have a simple, water-tight solution using only
Time::Local?

Think so.

sub daysago {
shift =~ /^(\d{4})-(\d{2})-(\d{2})$/
or die "Invalid date format";
require Time::Local;
import Time::Local 'timelocal';
my $diff = timelocal(0,0,0,(localtime $^T)[3..5])
- timelocal(0,0,0,$3,$2-1,$1-1900);
$diff >= 0 or die "Future date not allowed";
sprintf '%.0f', $diff / 86400
}

print daysago('2003-07-20'), "\n";

Note that in the presence of DST a day may have more or less
than 24 hours.

Doesn't the above sub take care of that?

I don't know, but it is only obviously correct if the interval
between the two times is a multiple of 24 hours.

Hey, how is your math? ;-) We know it may differ 1/24 day, and since
that it far less than 1/2, to me it's pretty obvious that sprintf()
makes it return the correct number of days.

Then there's the problem of non-existent and ambiguous times that
comes with DST.
Sometimes I feel that there is something religious about the faith in
using oversized modules. :(

There is a well-founded preference for peer-reviewed solutions over
ad-hoc ones.

Anno
 
A

Anno Siegel

Gunnar Hjalmarsson said:
Anno said:
Gunnar said:
Anno Siegel wrote:
Do you have a simple, water-tight solution using only
Time::Local?

Think so.

sub daysago {
shift =~ /^(\d{4})-(\d{2})-(\d{2})$/
or die "Invalid date format";
require Time::Local;
import Time::Local 'timelocal';
my $diff = timelocal(0,0,0,(localtime $^T)[3..5])
- timelocal(0,0,0,$3,$2-1,$1-1900);
$diff >= 0 or die "Future date not allowed";
sprintf '%.0f', $diff / 86400
}

print daysago('2003-07-20'), "\n";

Note that in the presence of DST a day may have more or less
than 24 hours.

Doesn't the above sub take care of that?

I don't know, but it is only obviously correct if the interval
between the two times is a multiple of 24 hours.

Hey, how is your math? ;-) We know it may differ 1/24 day, and since
that it far less than 1/2, to me it's pretty obvious that sprintf()
makes it return the correct number of days.

....supposing that the rounded number is indeed what is wanted in
this case. It may differ from the number of complete calendar days
between the dates.

Then there's the problem of non-existent and ambiguous times that
comes with DST.
Sometimes I feel that there is something religious about the faith in
using oversized modules. :(

There is a well-founded preference for peer-reviewed solutions over
ad-hoc ones.

Anno
 
G

Gunnar Hjalmarsson

Anno said:
Gunnar said:
Anno said:
Gunnar Hjalmarsson wrote:
Anno Siegel wrote:


sub daysago {
shift =~ /^(\d{4})-(\d{2})-(\d{2})$/
or die "Invalid date format";
require Time::Local;
import Time::Local 'timelocal';
my $diff = timelocal(0,0,0,(localtime $^T)[3..5])
- timelocal(0,0,0,$3,$2-1,$1-1900);
$diff >= 0 or die "Future date not allowed";
sprintf '%.0f', $diff / 86400
}

print daysago('2003-07-20'), "\n";

Note that in the presence of DST a day may have more or
less than 24 hours.

Doesn't the above sub take care of that?

I don't know, but it is only obviously correct if the interval
between the two times is a multiple of 24 hours.

Hey, how is your math? ;-) We know it may differ 1/24 day, and
since that it far less than 1/2, to me it's pretty obvious that
sprintf() makes it return the correct number of days.

...supposing that the rounded number is indeed what is wanted in
this case. It may differ from the number of complete calendar days
between the dates.

I have absolutely no idea what you are refering to here, Anno. Did you
see that the code disregards the first three elements that localtime()
returns? Could you possibly give an example when the function would
return anything else but the number of complete calendar days since
the date that is passed to it?
Then there's the problem of non-existent and ambiguous times that
comes with DST.

What's the nature of that problem?
 
A

Anno Siegel

Gunnar Hjalmarsson said:
Anno said:
Gunnar said:
Anno Siegel wrote:
Gunnar Hjalmarsson wrote:
Anno Siegel wrote:


sub daysago {
shift =~ /^(\d{4})-(\d{2})-(\d{2})$/
or die "Invalid date format";
require Time::Local;
import Time::Local 'timelocal';
my $diff = timelocal(0,0,0,(localtime $^T)[3..5])
- timelocal(0,0,0,$3,$2-1,$1-1900);
$diff >= 0 or die "Future date not allowed";
sprintf '%.0f', $diff / 86400
}

print daysago('2003-07-20'), "\n";

Note that in the presence of DST a day may have more or
less than 24 hours.

Doesn't the above sub take care of that?

I don't know, but it is only obviously correct if the interval
between the two times is a multiple of 24 hours.

Hey, how is your math? ;-) We know it may differ 1/24 day, and
since that it far less than 1/2, to me it's pretty obvious that
sprintf() makes it return the correct number of days.

...supposing that the rounded number is indeed what is wanted in
this case. It may differ from the number of complete calendar days
between the dates.

I have absolutely no idea what you are refering to here, Anno. Did you
see that the code disregards the first three elements that localtime()
returns? Could you possibly give an example when the function would
return anything else but the number of complete calendar days since
the date that is passed to it?

I don't remember saying it doesn't. It would be your job to prove
that it does, and (a lot harder) to describe the conditions under
which it does. Only the latter is relevant to my point.

My point is that the seemingly clear notion of the number of days
between two calendar dates must be re-defined in view of the fact
that two midnights aren't necessarily a multiple of 24 hours apart.
You assume that rounding is the answer, but other answers could be
given, which might differ by one under various circumstances.

At this point I might decide to use a module that (presumably)
has come up with a solution that is both consistent in itself
and with intuitive notions, and which is reasonably general
with respect to local DST variations.
What's the nature of that problem?

Some valid time specifications don't correspond to a point in time
(when a calendar hour has been jumped over), and others correspond
to two (when a calendar hour has been repeated). Granted, DST
regulations don't do that around midnight, but that is a restriction
in the validity of the algorithm, or it must be taken into account
anyway.

Anno
 
G

Gunnar Hjalmarsson

Anno said:
I don't remember saying it doesn't. It would be your job to prove
that it does, and (a lot harder) to describe the conditions under
which it does.

My "job"? You asked if I have "a simple, water-tight solution" using
only Time::Local, and I posted this code, which I claim is just that:

sub daysago {
shift =~ /^(\d{4})-(\d{2})-(\d{2})$/
or die "Invalid date format";
require Time::Local;
import Time::Local 'timelocal';
my $diff = timelocal(0,0,0,(localtime $^T)[3..5])
- timelocal(0,0,0,$3,$2-1,$1-1900);
$diff >= 0 or die "Future date not allowed";
sprintf '%.0f', $diff / 86400
}

print daysago('2003-07-20'), "\n";

It addresses the trivial task the OP asked for help with: Calculating
the number of days since a certain date.
My point is that the seemingly clear notion of the number of days
between two calendar dates must be re-defined in view of the fact
that two midnights aren't necessarily a multiple of 24 hours apart.

Re-defined? Out from which definition? And why?

The function computes the number of seconds between 00:00:00 at the
comparison date and 00:00:00 at today's date. Switching to or from DST
may result in that number being 3600 seconds less or more than a
multiple of 86400, but such a switch can never affect the full number
of calendar days after rounding by sprintf().
You assume that rounding is the answer, but other answers could be
given, which might differ by one under various circumstances.

Which answers would that be? Note that we are talking about comparing
dates. Time of the day is not an input, and should obviously not
affect the result.
At this point I might decide to use a module that (presumably) has
come up with a solution that is both consistent in itself and with
intuitive notions, and which is reasonably general with respect to
local DST variations.

Nothing wrong with doing so, of course. Personally I think twice
before using a non-standard module, since I usually work with programs
that are intended for distribution, and non-standard modules
complicates the distribution.
 
A

Anno Siegel

Gunnar Hjalmarsson said:
My "job"? You asked if I have "a simple, water-tight solution" using
only Time::Local, and I posted this code, which I claim is just that:

Quite. It's your algorithm and your claim.
sub daysago {
shift =~ /^(\d{4})-(\d{2})-(\d{2})$/
or die "Invalid date format";
require Time::Local;
import Time::Local 'timelocal';
my $diff = timelocal(0,0,0,(localtime $^T)[3..5])
- timelocal(0,0,0,$3,$2-1,$1-1900);
$diff >= 0 or die "Future date not allowed";
sprintf '%.0f', $diff / 86400
}

print daysago('2003-07-20'), "\n";

It addresses the trivial task the OP asked for help with: Calculating
the number of days since a certain date.
My point is that the seemingly clear notion of the number of days
between two calendar dates must be re-defined in view of the fact
that two midnights aren't necessarily a multiple of 24 hours apart.

Re-defined? Out from which definition? And why?

To calculate the number of cars in a train from its length, you divide
the length by the length of each car. That's fine as long as all
cars have the same length. Now DST comes along and introduces non-
standard long and short cars. For an arbitrary mixture of cars, the
method breaks down now. What saves it (with the introduction of
rounding) is the fact that DST introduces its non-standard cars in
particular ways. It would be necessary to describe exactly what
DST may do and what not (and to make sure that all local implementations
of DST comply) to establish the validity of the method. That is not
trivial.

Anno
 
G

Gunnar Hjalmarsson

Anno said:
It would be necessary to describe exactly what DST may do and what
not (and to make sure that all local implementations of DST comply)
to establish the validity of the method. That is not trivial.

Can you point me to the corresponding descriptions for Date::Calc and
Date::Manip?

I can't understand why you are trying to turn this trivial task into
rocket science. You are reasoning as if it was a general purpose
date/time module or a calendar app.
 
E

Eric Schwartz

Gunnar Hjalmarsson said:
Can you point me to the corresponding descriptions for Date::Calc and
Date::Manip?

Frankly, I like using Date::Calc because it's trivially obvious what
it does, and I don't have to work out whether some yobbo on the
Internet wrote a date-diff function properly or not. :) The fact that
it does all sorts of other things, including diffs between date/time
pairs, is a nice bonus.
I can't understand why you are trying to turn this trivial task into
rocket science. You are reasoning as if it was a general purpose
date/time module or a calendar app.

You're right, there's no reason I *couldn't* write such a function (or
just use yours) but I have absolutely no motivation to, given that
Date::Calc exists, and is relatively fast and easy to use.

-Eric
 
M

M.J.T. Guy

Anno Siegel said:
Do you have a simple, water-tight solution using only Time::Local?
Note that in the presence of DST a day may have more or less than 24
hours.

Easy - always do your calculations in GMT. Then DST issues never arise.


Mike Guy
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top