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 Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

comparing a date to see if it falls equal to or in between two others 1

Status
Not open for further replies.

spewn

Programmer
Joined
May 7, 2001
Messages
1,034
i'm working on an event submission script.

the user submits an event and the event could be 1 day, or stretch over multiple days.

i also have an event calendar. i am able to click on a certain day and see if there is anything booked on that day.

but if an event is booked on multiple days, the event is shown on the calendar only on the first day.

if i can figure out if the date clicked on has anything booked on or through it, that would be helpful...

so far, this is what i'm working on:
Code:
$minDate='8/4/2007';
$date1='1/4/2008';
$maxDate='10/4/2009';

@dateVar=split(/\//,$date1);
$month1=@dateVar[0];
$day1=@dateVar[1];
$year1=@dateVar[2];

@dateVar2=split(/\//,$minDate);
$minmonth=@dateVar2[0];
$minday=@dateVar2[1];
$minyear=@dateVar2[2];

@dateVar3=split(/\//,$maxDate);
$maxmonth=@dateVar3[0];
$maxday=@dateVar3[1];
$maxyear=@dateVar3[2];

$test='is not between!';

if (($year1 >= $minyear)&&($year1 <= $maxyear)) {
 if ($year1 > $minyear) {
  if ($year1 < $maxyear) {
   if (($month1 >= $minmonth)&&($month1 <= $maxmonth)) {
    if ($month1 > $minmonth) {
     if ($month1 < $maxmonth) {
      if (($day1 >= $minday)&&($day1 <= $maxday)) {
       if ($day1 > $minday) {
        if ($day1 < $maxday) {
        $test='is between';
        }
        else {day is equal to maxday}
       }
       else {day is equal to minday}
      }
     }
     else {month is equal to maxmonth}
    }
    else {month is equal to minmonth}
   }
  }
  else {year is equal to max year}
 }
 else {year is equal to min year}
}
i'm just getting started, and i know that every instance where the month, day or year is equal to the min or max, i'm gonna be running more conditionals. it's gonna be very intense.

is there a way to do this, easier? i found this online:
Code:
if (date.getTime() >= minDate.getTime() && date.getTime() <= maxDate.getTime()) {
   throw new DateOutOfRangeException(date.toString());
}

i'm not sure if i can use it.

i only have Date::Manip module installed.

thanks!

- g
 
Doing date arithmetic yourself is insane. If you have Date::Manip installed, why not use it?

From the Date::Manip docs to compare two dates (modified to put in your data):
Code:
  # not the module takes US formatted dates,
  # so if this is supposed to be the 8th of April,
  # you'll have to reverse the day and month
  $string1='8/4/2007';
  $string2='1/4/2008';
 
  $date1 = ParseDate($string1);
  $date2 = ParseDate($string2);
  $flag = Date_Cmp($date1,$date2);
  if ($flag<0) {
    # date1 is earlier
  } elsif ($flag==0) {
    # the two dates are identical
  } else {
    # date2 is earlier
  }
 
And if for some reason Date::Manip or other date module is not available use the core module Time::Local to convert the dates into epoch seconds then compare them. This is actually quite easy to do but make sure to read the Time::Local documentation thoroughly.

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
ok, i tried to modify your code a bit to accomodate my needs, but it's not quite right...(it's not working)...

Code:
$stringMin='4/1/2007';
$thisDate='4/2/2007';
$stringMax='4/3/2007';

@dateVar=split(/\//,$thisDate);
$month1=@dateVar[0];
$day1=@dateVar[1];
$year1=@dateVar[2];
$thisDate=$day1.'/'.$month1.'/'.$year1;

@dateVar2=split(/\//,$stringMin);
$minmonth=@dateVar2[0];
$minday=@dateVar2[1];
$minyear=@dateVar2[2];
$stringMin=$minday.'/'.$minmonth.'/'.$minyear;

@dateVar3=split(/\//,$stringMax);
$maxmonth=@dateVar3[0];
$maxday=@dateVar3[1];
$maxyear=@dateVar3[2];
$stringMax=$maxday.'/'.$maxmonth.'/'.$maxyear;
 
$dateMin = ParseDate($stringMin);
$dateMax = ParseDate($stringMax);
$flag1 = Date_Cmp($thisDate,$dateMin);
$flag2 = Date_Cmp($thisDate,$dateMax);

if ($flag1>=0) {
 if ($flag2<=0) {$result=$thisDate.' is between '.$stringMin.' and '.$stringMax;}
}

print $cgi->header(-cookie=>$cookie);

print $xresult;

clearly the date is have is between the min and max, but the result isn't printing...

any edit/modification would be helpful...i'm gonna keep trying...

- g
 
duh...i think i got it.

i had to put an 'x' in front of the result variable.

thanks. i'm retesting it.

- g
 
ok, it's still not working. it works, but i used these dates:

$stringMin='4/1/2008';
$thisDate='3/2/2008';
$stringMax='4/3/2009';

and it said that $thisDate was in between the min and max...does anyone see where i went wrong?

- g

Code:
$stringMin='4/1/2008';
$thisDate='3/2/2008';
$stringMax='4/3/2009';

@dateVar=split(/\//,$thisDate);
$month1=@dateVar[0];
$day1=@dateVar[1];
$year1=@dateVar[2];
$thisDate2=$day1.'/'.$month1.'/'.$year1;

@dateVar2=split(/\//,$stringMin);
$minmonth=@dateVar2[0];
$minday=@dateVar2[1];
$minyear=@dateVar2[2];
$stringMin2=$minday.'/'.$minmonth.'/'.$minyear;

@dateVar3=split(/\//,$stringMax);
$maxmonth=@dateVar3[0];
$maxday=@dateVar3[1];
$maxyear=@dateVar3[2];
$stringMax2=$maxday.'/'.$maxmonth.'/'.$maxyear;
 
$dateMin2 = ParseDate($stringMin2);
$dateMax2 = ParseDate($stringMax2);
$flag1 = Date_Cmp($thisDate2,$dateMin2);
$flag2 = Date_Cmp($thisDate2,$dateMax2);

if ($flag1>=0) {
 if ($flag2<=0) {$xresult=$thisDate.' is between '.$stringMin.' and '.$stringMax;}
}

print $cgi->header(-cookie=>$cookie);

print $xresult;
 
Your code seems quite long, there would be an easier solution. I would think about using:

Code:
my ($time)=time;

But thats possibly also a long system if using it within your context.
 
$month1=@dateVar[0]; ponder
You should perhaps go a bit deeper into perl before going on.

It's not exactly kosher but it does work.

Here is an example using Time::Local to compare dates that are in human readable format:

Code:
[url=http://perldoc.perl.org/functions/use.html][black][b]use[/b][/black][/url] [green]strict[/green][red];[/red]
[black][b]use[/b][/black] [green]warnings[/green][red];[/red]
[black][b]use[/b][/black] [green]Time::Local[/green][red];[/red]

[gray][i]# month/day/year[/i][/gray]
[url=http://perldoc.perl.org/functions/my.html][black][b]my[/b][/black][/url] [blue]$d1[/blue] = [red]'[/red][purple]12/25/2007[/purple][red]'[/red][red];[/red]
[black][b]my[/b][/black] [blue]$d2[/blue] = [red]'[/red][purple]7/4/2007[/purple][red]'[/red][red];[/red]
[black][b]my[/b][/black] [blue]$d3[/blue] = [red]'[/red][purple]10/31/2007[/purple][red]'[/red][red];[/red]

[black][b]my[/b][/black] [blue]@dates[/blue] = [maroon]sort_dates[/maroon][red]([/red][blue]$d1[/blue],[blue]$d2[/blue],[blue]$d3[/blue][red])[/red][red];[/red]

[url=http://perldoc.perl.org/functions/print.html][black][b]print[/b][/black][/url] [red]"[/red][purple]Highest date is [blue]$dates[/blue][-1][purple][b]\n[/b][/purple][/purple][red]"[/red][red];[/red]
[black][b]print[/b][/black] [red]"[/red][purple]Lowest date is [blue]$dates[/blue][0][purple][b]\n[/b][/purple][/purple][red]"[/red][red];[/red]
[black][b]print[/b][/black] [red]"[/red][purple]Date(s) between high and low is [/purple][red]"[/red], [url=http://perldoc.perl.org/functions/join.html][black][b]join[/b][/black][/url][red]([/red][red]'[/red][purple],[/purple][red]'[/red],[blue]@dates[/blue][red][[/red][fuchsia]1..[/fuchsia][blue]$#dates[/blue]-[fuchsia]1[/fuchsia][red]][/red][red])[/red][red];[/red]

[url=http://perldoc.perl.org/functions/sub.html][black][b]sub[/b][/black][/url] [maroon]sort_dates[/maroon] [red]{[/red]
   [black][b]my[/b][/black] [blue]%t[/blue] = [url=http://perldoc.perl.org/functions/map.html][black][b]map[/b][/black][/url] [red]{[/red] [red]m#[/red][purple]([purple][b]\d[/b][/purple]+)/([purple][b]\d[/b][/purple]+)/([purple][b]\d[/b][/purple]+)[/purple][red]#[/red][red];[/red] [blue]$_[/blue] => [maroon]timelocal[/maroon][red]([/red][fuchsia]0[/fuchsia],[fuchsia]0[/fuchsia],[fuchsia]0[/fuchsia],[blue]$2[/blue],[blue]$1[/blue]-[fuchsia]1[/fuchsia],[blue]$3[/blue][red])[/red][red]}[/red] [blue]@_[/blue][red];[/red]
   [url=http://perldoc.perl.org/functions/return.html][black][b]return[/b][/black][/url][red]([/red] [url=http://perldoc.perl.org/functions/sort.html][black][b]sort[/b][/black][/url] [red]{[/red][blue]$t[/blue][red]{[/red][blue]$a[/blue][red]}[/red]<=>[blue]$t[/blue][red]{[/red][blue]$b[/blue][red]}[/red][red]}[/red] [url=http://perldoc.perl.org/functions/keys.html][black][b]keys[/b][/black][/url] [blue]%t[/blue][red])[/red][red];[/red]
[red]}[/red]
[tt]------------------------------------------------------------
Pragmas (perl 5.8.8) used :
[ul]
[li]strict - Perl pragma to restrict unsafe constructs[/li]
[li]warnings - Perl pragma to control optional warnings[/li]
[/ul]
Core (perl 5.8.8) Modules used :
[ul]
[li]Time::Local - efficiently compute time from local and GMT time[/li]
[/ul]
[/tt]

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
$month1=@dateVar[0];
You should perhaps go a bit deeper into perl before going on.

wow. i'm as deep into perl as you are into bedside manner.

anyway, what's wrong with it...

thanks kevin for your help...but i like to use stuff that i know...i really want my original code to work.

- g
 
Whats wrong with it is that it is long deprecated syntax that perl stills supports but may not support in future revisions of perl.

@array[n] is an array slice, not a scalar like $array[n] is. That is why you can do something like this:

my ($var1,$var2,$var3) = @array[0,2,5];

I don't think prex1 meant to insult or offend you, but I guess he can clear that up with you if he wishes to.

The code I posted should work for you, it is fairly easy to understand and requires no extra modules. My personal opinion is loading up Date::Manip to do one easy date calculation is not worth the overhead but it is if
you need to do more things with your dates. But of ourse you shold proceed how you think is best.

-Kevin



------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
KevinADC said:
Code:
[url=http://perldoc.perl.org/functions/sub.html][black][b]sub[/b][/black][/url] [maroon]sort_dates[/maroon] [red]{[/red]
   [url=http://perldoc.perl.org/functions/my.html][black][b]my[/b][/black][/url] [blue]%t[/blue] = [url=http://perldoc.perl.org/functions/map.html][black][b]map[/b][/black][/url] [red]{[/red] [red]m#[/red][purple]([purple][b]\d[/b][/purple]+)/([purple][b]\d[/b][/purple]+)/([purple][b]\d[/b][/purple]+)[/purple][red]#[/red][red];[/red] [blue]$_[/blue] => [maroon]timelocal[/maroon][red]([/red][fuchsia]0[/fuchsia],[fuchsia]0[/fuchsia],[fuchsia]0[/fuchsia],[blue]$2[/blue],[blue]$1[/blue]-[fuchsia]1[/fuchsia],[blue]$3[/blue][red])[/red][red]}[/red] [blue]@_[/blue][red];[/red]
   [url=http://perldoc.perl.org/functions/return.html][black][b]return[/b][/black][/url][red]([/red] [url=http://perldoc.perl.org/functions/sort.html][black][b]sort[/b][/black][/url] [red]{[/red][blue]$t[/blue][red]{[/red][blue]$a[/blue][red]}[/red]<=>[blue]$t[/blue][red]{[/red][blue]$b[/blue][red]}[/red][red]}[/red] [url=http://perldoc.perl.org/functions/keys.html][black][b]keys[/b][/black][/url] [blue]%t[/blue][red])[/red][red];[/red]
[red]}[/red]

There's one small bug with that code Kevin. Obviously, it's important for efficiency sake to cache the unixtime translation of the dates, but you should access the original dates directly via "@_" instead of indirectly via "keys %t". Unless you intentionally want to filter out duplicate dates that is.


An alternative way of doing this is to reformat the dates into greater to smaller length of times. There are times when I find this better when there is a chance that the dates might be less than epoch. This is easily done using a Kevin's code as a template though:

Code:
[url=http://perldoc.perl.org/functions/use.html][black][b]use[/b][/black][/url] [green]strict[/green][red];[/red]
[black][b]use[/b][/black] [green]warnings[/green][red];[/red]

[gray][i]# month/day/year[/i][/gray]
[url=http://perldoc.perl.org/functions/my.html][black][b]my[/b][/black][/url] [blue]@dates[/blue] = [red]qw([/red][purple]12/25/2007 7/4/2007 10/31/2007[/purple][red])[/red][red];[/red]

[black][b]my[/b][/black] [blue]@sorted[/blue] = [maroon]sort_MDYYYY[/maroon][red]([/red][blue]@dates[/blue][red])[/red][red];[/red]

[url=http://perldoc.perl.org/functions/print.html][black][b]print[/b][/black][/url] [red]"[/red][purple]Highest date is [blue]$sorted[/blue][-1][purple][b]\n[/b][/purple][/purple][red]"[/red][red];[/red]
[black][b]print[/b][/black] [red]"[/red][purple]Lowest date is [blue]$sorted[/blue][0][purple][b]\n[/b][/purple][/purple][red]"[/red][red];[/red]
[black][b]print[/b][/black] [red]"[/red][purple]Date(s) between high and low is [/purple][red]"[/red], [url=http://perldoc.perl.org/functions/join.html][black][b]join[/b][/black][/url][red]([/red][red]'[/red][purple],[/purple][red]'[/red],[blue]@sorted[/blue][red][[/red][fuchsia]1..[/fuchsia][blue]$#dates[/blue]-[fuchsia]1[/fuchsia][red]][/red][red])[/red][red];[/red]

[url=http://perldoc.perl.org/functions/sub.html][black][b]sub[/b][/black][/url] [maroon]sort_MDYYYY[/maroon] [red]{[/red]
	[black][b]my[/b][/black] [blue]%order[/blue] = [url=http://perldoc.perl.org/functions/map.html][black][b]map[/b][/black][/url] [red]{[/red]
		[red]m{[/red][purple]([purple][b]\d[/b][/purple]+)/([purple][b]\d[/b][/purple]+)/([purple][b]\d[/b][/purple]+)[/purple][red]}[/red][red];[/red] [gray][i]# Assumes M/D/YYYY[/i][/gray]
		[blue]$_[/blue] => [url=http://perldoc.perl.org/functions/sprintf.html][black][b]sprintf[/b][/black][/url][red]([/red][red]"[/red][purple]%04d%02d%02d[/purple][red]"[/red], [blue]$3[/blue], [blue]$1[/blue], [blue]$2[/blue][red])[/red]
	[red]}[/red] [blue]@_[/blue][red];[/red]
	[url=http://perldoc.perl.org/functions/return.html][black][b]return[/b][/black][/url] [url=http://perldoc.perl.org/functions/sort.html][black][b]sort[/b][/black][/url] [red]{[/red][blue]$order[/blue][red]{[/red][blue]$a[/blue][red]}[/red] cmp [blue]$order[/blue][red]{[/red][blue]$b[/blue][red]}[/red][red]}[/red] [blue]@_[/blue][red];[/red]
[red]}[/red]

The only problem with this type of technique is that it does not get to take advantage of the data validation embedded withing Time::Local. However, that can easily be added to the creation of the ordered hash.

- Miller
 
There's one small bug with that code Kevin. Obviously, it's important for efficiency sake to cache the unixtime translation of the dates, but you should access the original dates directly via "@_" instead of indirectly via "keys %t". Unless you intentionally want to filter out duplicate dates that is.

It's a good point. At this junction it's hard to say if one way or the other would be better: the hash keys or the array. I thought about it for a moment and filtering out duplicates seemed logical to me, but in a practical application with other considerations to take into account it might not.

There are times when I find this better when there is a chance that the dates might be less than epoch.

That is also a good point. In this specific case it seems like that would not be a consideration though (booking events). But epoch time does have it's limitations.

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
spewn, OK I was a bit rude, but we should consider ourselves all as friends on this fora, and you should always say barely the truth with a real friend...[smile]
In trying to get your pardon, I'll propose an approach different from all the above, that I'm sure you'll like, as you don't like the [tt]time[/tt] function (that should be the only way of handling dates internally in a perl script...).
The point is that if you express a date as yyyy/mm/dd, then the dates are lexically and timely in sort order. So just do the following:
Code:
$stringMin='4/1/2008';
$thisDate='3/2/2008';
$stringMax='4/3/2009';

$stringMin=myformatDate($stringMin);
$thisDate=myformatDate($thisDate);
$stringMax=myformatDate($stringMax);

$flag1=$thisDate ge $stringMin;
$flag2=$stringMax ge $thisDate;

$xresult=$thisDate.' is between '.$stringMin.' and '.$stringMax if$flag1&&$flag2;

sub myformatDate{
  my($thisDate)=@_;
  my($month,$day,$year)=split(/\//,$thisDate);
  return sprintf("%4d/%02d/%02d",$year,$month,$day);
}

prex1
: Online tools for structural design
: Magnetic brakes for fun rides
: Air bearing pads
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top