Wie kann ich überprüfen, ob ein Datum in einem bestimmten Bereich liegt?

84

Wenn Sie ein $start_dateund haben $end_date, wie können Sie überprüfen, ob ein vom Benutzer angegebenes Datum in diesen Bereich fällt?

z.B

$start_date = '2009-06-17';

$end_date = '2009-09-05';

$date_from_user = '2009-08-28'; 

Im Moment sind die Daten Zeichenfolgen. Würde es helfen, sie in Zeitstempel-Ganzzahlen umzuwandeln?

meleyal
quelle
Es würde helfen, dann hätten Sie Zugriff auf alle Funktionen zur Datumsmanipulation, die es gibt.
ChrisF
3
Seien Sie nur vorsichtig mit der Zeitstempelbeschränkung, da Unix-Zeitstempel in der Epoche beginnen, die am 1. Januar 1970 (1970-01-01) liegt, sodass Sie sich beim Testen von Daten vor 1970 lustig verhalten können.
Shadi Almosri
1
@Shadi Du weißt, dass es so etwas wie NEGATIVE Zahlen gibt, oder?
Jeremy Logan
@fiXedd das gleiche Grundproblem besteht jedoch - selbst wenn negative Zeitstempel zugelassen werden, können 32-Bit-Zeitstempel keine Daten vor 1902 darstellen.
Frank Farmer

Antworten:

119

Das Konvertieren in Zeitstempel ist der richtige Weg, wenn Sie strtotime verwenden , z

$start_date = '2009-06-17';

$end_date = '2009-09-05';

$date_from_user = '2009-08-28';

check_in_range($start_date, $end_date, $date_from_user);


function check_in_range($start_date, $end_date, $date_from_user)
{
  // Convert to timestamp
  $start_ts = strtotime($start_date);
  $end_ts = strtotime($end_date);
  $user_ts = strtotime($date_from_user);

  // Check that user date is between start & end
  return (($user_ts >= $start_ts) && ($user_ts <= $end_ts));
}
ConroyP
quelle
Funktioniert super. Vielen Dank.
GeneCode
46

Es ist nicht erforderlich, für den Vergleich in einen Zeitstempel zu konvertieren, da die Zeichenfolgen als Daten im kanonischen Format 'JJJJ-MM-TT' validiert werden.

Dieser Test wird funktionieren:

( ( $date_from_user >= $start_date ) && ( $date_from_user <= $end_date ) )

gegeben:

$start_date     = '2009-06-17';
$end_date       = '2009-09-05';
$date_from_user = '2009-08-28';

HINWEIS: Der Vergleich solcher Zeichenfolgen ermöglicht "ungültige" Daten, z. B. (32. Dezember) '2009-13-32', und seltsam formatierte Zeichenfolgen '2009/3/3', sodass ein Zeichenfolgenvergleich NICHT gleichwertig ist ein Datums- oder Zeitstempelvergleich. Dies funktioniert NUR, wenn die Datumswerte in den Zeichenfolgen in einem konsistenten und kanonischen Format vorliegen.

BEARBEITEN Sie , um hier eine Notiz hinzuzufügen und das Offensichtliche zu erläutern.

Mit KONSISTENT meine ich zum Beispiel, dass die verglichenen Zeichenfolgen das gleiche Format haben müssen: Der Monat muss immer aus zwei Zeichen bestehen, der Tag muss immer aus zwei Zeichen bestehen und das Trennzeichen muss immer ein Bindestrich sein. Wir können "Zeichenfolgen", die nicht aus vier Zeichenjahr, zwei Zeichenmonaten und zwei Zeichen bestehen, nicht zuverlässig vergleichen. Wenn wir zum Beispiel eine Mischung aus einem Zeichen und zwei Zeichenmonaten in den Zeichenfolgen hätten, würden wir im Vergleich '2009-9-30'zu ein unerwartetes Ergebnis erzielen '2009-10-11'. Wir sehen menschlich "9" als kleiner als "10", aber ein Zeichenfolgenvergleich wird '2009-9'als größer als " '2009-1'. Wir brauchen nicht unbedingt ein Bindestrich-Trennzeichen. Wir könnten genauso gut Strings in vergleichen'YYYYMMDD'Format; Wenn es ein Trennzeichen gibt, muss es immer da und immer gleich sein.

Mit CANONICAL meine ich ein Format, das zu Zeichenfolgen führt, die in Datumsreihenfolge sortiert werden. Das heißt, die Zeichenfolge wird zuerst "Jahr", dann "Monat" und dann "Tag" darstellen. Wir können Zeichenfolgen im 'MM-DD-YYYY'Format nicht zuverlässig vergleichen , da dies nicht kanonisch ist. Ein Zeichenfolgenvergleich würde den MM(Monat) vor dem Vergleich YYYY(Jahr) vergleichen, da der Zeichenfolgenvergleich von links nach rechts funktioniert.) Ein großer Vorteil des Zeichenfolgenformats 'JJJJ-MM-TT' besteht darin, dass es kanonisch ist. In diesem Format dargestellte Daten können zuverlässig als Zeichenfolgen verglichen werden.

[NACHTRAG]

Wenn Sie sich für die PHP-Zeitstempelkonvertierung entscheiden, beachten Sie die Einschränkungen.

Auf einigen Plattformen unterstützt PHP keine Zeitstempelwerte früher als 1970-01-01 und / oder später als 2038-01-19. (Das ist die Natur der 32-Bit-Ganzzahl des Unix-Zeitstempels.) Spätere Versionen von PHP (5.3?) Soll dies beheben.

Die Zeitzone kann auch ein Problem sein, wenn Sie beim Konvertieren von Zeichenfolge zu Zeitstempel und von Zeitstempel zurück zu Zeichenfolge nicht darauf achten, dieselbe Zeitzone zu verwenden.

HTH

spencer7593
quelle
1
Dieser ist interessant.
Ionuț G. Stan
1
Obwohl ohne Casting Probleme auftreten können, wenn die Werte von $ date_from_user, $ start_date oder $ end_date keine Datumsangaben sind. Dh $ end_date = 'Balh Blah' .. wird definitiv nicht richtig funktionieren
Mike Dinescu
@ spencer7593, haben Sie einige Referenzen für dieses Verhalten?
Ionuț G. Stan
2
Sie könnten checkdate () verwenden, um zu validieren
meleyal
1
@Sergio: Ja, der gleiche Zeichenfolgenvergleich funktioniert für Zeitwerte, solange die Zeichenfolgen in einem kanonischen Standardformat vorliegen (dh 24-Stunden-Uhr, Mitternacht als '00: 00: 00 ', die letzte Sekunde vor Mitternacht als' 23:59:59 '. Um sicherzustellen, dass der Zeichenfolgenvergleich "funktioniert", müssen Sie sicherstellen, dass die Zeichenfolgendarstellungen des Zeitwerts in einem garantierten Format vorliegen.
spencer7593
46

Verwenden Sie die DateTime-Klasse, wenn Sie über PHP 5.3+ verfügen. Einfacher zu bedienen, bessere Funktionalität.

DateTime unterstützt intern Zeitzonen. Die anderen Lösungen liegen bei Ihnen.

<?php    
/**
 * @param DateTime $date Date that is to be checked if it falls between $startDate and $endDate
 * @param DateTime $startDate Date should be after this date to return true
 * @param DateTime $endDate Date should be before this date to return true
 * return bool
 */
function isDateBetweenDates(DateTime $date, DateTime $startDate, DateTime $endDate) {
    return $date > $startDate && $date < $endDate;
}

$fromUser = new DateTime("2012-03-01");
$startDate = new DateTime("2012-02-01 00:00:00");
$endDate = new DateTime("2012-04-30 23:59:59");

echo isDateBetweenDates($fromUser, $startDate, $endDate);
alter Zauberer
quelle
Sie würden dies wahrscheinlich in eine Funktion umwandeln, die drei Parameter akzeptiert, und einen Booleschen Wert zurückgeben. Sollte sehr einfach zu testen sein?
Oldwizard
Ich würde sagen, dass die Funktion true zurückgeben sollte, 2012-02-01dazwischen liegt 2012-02-01 ... 2014-04-30 23:59:59.
Salman A
1
Ich bevorzuge DateTimeimmer die skizzenhaften Zeitfunktionen, die PHP sofort bietet. Um das Start- und Enddatum in diese Prüfung return $date >= $startDate && $date <= $endDate;
einzubeziehen,
@zanderway sagen Sie, dass die> Standardeinstellungen ein "Tages" -Vergleich und kein Sekundenvergleich sind? $ startDate hat Sekunden angegeben, also frage ich mich, ob das "> =" wirklich notwendig ist?
PJ Brunet
4
$startDatedt = strtotime($start_date)
$endDatedt = strtotime($end_date)
$usrDatedt = strtotime($date_from_user)

if( $usrDatedt >= $startDatedt && $usrDatedt <= $endDatedt)
{
   //..falls within range
}
Stan R.
quelle
Das beinhaltet keine genauen Übereinstimmungen mit dem Start- oder Enddatum
TheTXI
OP hat nicht nach Inklusivspielen gefragt.
Jeremy Logan
3

Konvertieren Sie dann beide Daten in Zeitstempel

Pseudocode:

if date_from_user > start_date && date_from_user < end_date
    return true
Tal
quelle
Möglicherweise möchten Sie es so bearbeiten, dass Sie auch start_date und end_date in den Bereich aufnehmen. Wenn jetzt date_from_user gleich ist, wird es nicht gezählt.
TheTXI
Das OP hat keine inklusiven oder exklusiven Bereiche angegeben, daher überlasse ich es ihnen, die zu verwendende Strategie auszuwählen
Glen
3

Unter der Annahme, dass der Benutzer intelligent genug ist, um Ihnen gültige Daten zu geben, müssen Sie in dem von Ihnen angegebenen Format nicht zuerst in ein Datum konvertieren, sondern können sie als Zeichenfolgen vergleichen.

richardtallent
quelle
1
Zu diesem Zeitpunkt im Code wurden die Daten bereits validiert
meleyal
3
$start_date="17/02/2012";
$end_date="21/02/2012";
$date_from_user="19/02/2012";

function geraTimestamp($data)
{
    $partes = explode('/', $data); 
    return mktime(0, 0, 0, $partes[1], $partes[0], $partes[2]);
}


$startDatedt = geraTimestamp($start_date); 
$endDatedt = geraTimestamp($end_date);
$usrDatedt = geraTimestamp($date_from_user);

if (($usrDatedt >= $startDatedt) && ($usrDatedt <= $endDatedt))
{ 
    echo "Dentro";
}    
else
{
    echo "Fora";
}
Paulo Henrique
quelle
2

Konvertieren Sie sie in Datums- oder Zeitstempel-Ganzzahlen und überprüfen Sie dann, ob $ date_from_user <= $ end_date und> = $ start_date ist

TheTXI
quelle
3
Könnten Sie klarstellen, ob Sie sie in Daten umwandeln sollen? Wie würdest du das machen? Ich dachte, PHP hat keinen Datumstyp?
Meleyal
2

Sie können dies versuchen:

//custom date for example
$d1 = new DateTime("2012-07-08");
$d2 = new DateTime("2012-07-11");
$d3 = new DateTime("2012-07-08");
$d4 = new DateTime("2012-07-15");

//create a date period object
$interval = new DateInterval('P1D');
$daterange = iterator_to_array(new DatePeriod($d1, $interval, $d2));
$daterange1 = iterator_to_array(new DatePeriod($d3, $interval, $d4));
array_map(function($v) use ($daterange1) { if(in_array($v, $daterange1)) print "Bingo!";}, $daterange);
Ilya
quelle
1
Versionshinweis: iterator_to_array()ist verfügbar seit PHP 5.1
Raptor
0

Ich fand diese Methode am einfachsten:

$start_date = '2009-06-17';
$end_date = '2009-09-05';
$date_from_user = '2009-08-28';

$start_date = date_create($start_date);
$date_from_user = date_create($date_from_user);
$end_date = date_create($end_date);

$interval1 = date_diff($start_date, $date_from_user);
$interval2 = date_diff($end_date, $date_from_user);

if($interval1->invert == 0){
  if($interval2->invert == 1){

     // if it lies between start date and end date execute this code

  }
}
iniravpatel
quelle