2010-03-15 10 views
10

Ich kann nicht glauben, dass ich noch nie auf diesen zuvor gestoßen bin.Wie strtotime Analysedaten im australischen (d. H. UK) Format erstellt werden: TT/MM/JJJJ?

Grundsätzlich analysiere ich den Text in vom Menschen erstellten Textdokumenten und eines der Felder, die ich analysieren muss, ist ein Datum und eine Uhrzeit. Da ich in Australien bin, sind Daten wie formatiert, aber strtotime möchte nur als ein US-formatiertes Datum analysieren. Auch explodieren durch / wird nicht funktionieren, weil, wie ich schon erwähnte, diese Dokumente sind handgeschrieben und einige von ihnen nehmen die Form von d M yy.

Ich habe mehrere Kombinationen von setlocale ausprobiert, aber egal was ich versuche, die Sprache ist immer auf US-Englisch eingestellt.

Ich bin ziemlich sicher, Setlocale ist der Schlüssel hier, aber ich bin nicht in der Lage, den richtigen Code zu treffen. Versuchte diese:

  • au
  • au-en
  • en_AU
  • Australien
  • aus

Alles andere kann ich versuchen?

Zum besseren Verständnis: Ich verwende IIS mit einer Windows-Box.

Vielen Dank :)

Iain

Beispiel:

$mydatetime = strtotime("9/02/10 2.00PM"); 
echo date('j F Y H:i', $mydatetime); 

Produziert

2 September 2010 14:00 

Ich möchte es produzieren:

9 February 2010 14:00 

Meine Lösung

ich die Zecke auf eine der Antworten zu geben, wie es hier viel einfacher zu lesende Lösung zu mir ist, aber hier ist, was ich habe kommen mit:

  • 0 oder:

    $DateTime = "9/02/10 2.00PM"; 
    $USDateTime = preg_replace('%([0-3]?[0-9]{1})\s*?[\./ ]\s*?((?:1[0-2])|0?[0-9])\s*?[./ ]\s*?(\d{4}|\d{2})%', '${2}/${1}/${3}', $DateTime); 
    echo date('j F Y H:i',strtotime($USDateTime)); 
    

    Weil ich auf die Benutzer mit ihrem termin~~POS=TRUNC in Einklang stehen nicht verlassen können, ich habe meine regex ein bisschen komplizierter gemacht 1 Ziffer zwischen 0 und 3

  • 1 Ziffer zwischen 0 und 9 - ja, dies entspricht 37 als gültiges Datum, aber ich denke, die Regex ist schon groß genug!
  • Konnte einige Leerräume sein
  • Begrenzender Buchstabe (a '.'A '/' oder a' ‚)
  • Könnte einig Leer
  • sein Entweder:
    • eine Zahl zwischen 10 und 12 OR
    • eine Zahl zwischen 1 und 9 mit einem optionalen führenden 0
  • Könnte einig Leer
  • begrenzendes Zeichen sein, (a ' ' a '/' oder a'')
  • Könnte einiger Leer seine
  • Entweder:
    • A Nummer 2 Ziffern lang ODER
    • Eine Reihe 4 Ziffern lang

Hoffentlich wird dies die meisten Arten von Datum schriftlich passen ...

+0

Willst du es nicht produzieren? 9. Februar 2010 14: 00'? Oder habt ihr nur 11 Monate im Jahr? –

+0

Ja, bemerkte dies und änderte es. Kaffee ist noch nicht eingetreten. :) –

+0

Diese Frage könnte Ihnen helfen http://stackoverflow.com/questions/5597833/strange-behaviour-of-my-code-with-strtotime/5597905#5597905 – Twelve47

Antwort

19

Es gibt eine schnelle Lösung, die strtotime PHP in mit dem britischen Datumsformat zu zwingen scheint. Das heißt: Ersetzen Sie alle '/' in der eingehenden Zeichenfolge durch ein '-'.

Beispiel:

date('Y-m-d', strtotime('01/04/2011')); 

Würde produzieren: 2011-01-04

date('Y-m-d', strtotime('01-04-2011')); 

produzieren würde: 2011-04-01

Sie könnten str_replace verwenden zu erreichen Dies.

Beispiel:

str_replace('/', '-', '01/04/2011'); 

EDIT:

Wie in den Kommentaren erwähnt, dies funktioniert, weil PHP Schrägstriche als amerikanische und Punkte/Striche als europäische interpretiert.

Ich habe diesen Trick ausgiebig benutzt und hatte bisher keine Probleme.

Wenn jemand gute Gründe hat, dies nicht zu benutzen, bitte Kommentar.

+2

http://solidgone.org/PHP-strtotime-assumptions-with-European-and-American-andate-formats beschreibt die "Begründung" dahinter. Bindestriche schlagen ISO-Datumsformat vor, Punkte deuten auf Europäisch hin, und Schrägstriche sind amerikanisch. Nächste Frage: Aber warum ist das? –

+0

Frage war über unterschiedliche Reihenfolge von Monat und Tag in dem Datum nicht über Punkte und Bindestriche. –

+0

@VladimirSerykh Lesen Sie die Frage erneut. Es besagt eindeutig, dass "Daten wie TT/MM/JJJJ formatiert" sind, was bedeutet, dass die Daten des Fragestellers mit Schrägstrichen formatiert wurden, aber die Reihenfolge falsch war. Ich schlug vor, diese Schrägstriche in Bindestriche umzuwandeln, die die Reihenfolge korrigieren. –

1

setlocale () saugt genau den Grund, den du beschreibst: Du weißt nie, was du bekommen wirst. Am besten, die Zeichenfolge manuell zu verarbeiten.

Zend Framework Zend_Date ist eine Alternative, die eine genauere und konsistentere Datenverarbeitung verspricht. Ich habe selbst noch keine Erfahrung damit, nur damit anzufangen, aber bis jetzt mag ich es.

+0

Ja, das ist irgendwie, was ich am Ende getan habe . Nun, eigentlich habe ich die Zeichenfolge einfach neu formatiert, so dass UK-Daten zu US-Daten werden und bis jetzt hat es an all meinen Testfällen funktioniert - yay! –

3

Das Problem ist, dass strtotime kein Format Argument dauert. Was ist mit strptime?

+0

Dang, hätte ich gerne versucht, aber ich bin in einer WIMP-Umgebung :( –

1

Ah, das alte Problem, das wir australischen Glück haben.

Was ich in der Vergangenheit getan haben, ist so etwas wie dieses

public static function getTime($str) { // 3/12/2008 

     preg_match_all('/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/', $str, $matches); 

     return (isset($matches[0][0])) ? strtotime($matches[3][0] . '-' . $matches[2][0] . '-' . $matches[1][0]) : NULL; 

    } 

Obwohl dies in diesem Format dd/mm/yyyy auf Daten beruht.

Sie können wahrscheinlich eine andere Regex oder so verwenden, um von d M yy zu konvertieren oder eine modifizierte zu verwenden. Ich weiß nicht, ob dies richtig wäre, aber es kann ein Anfang sein:

/^(\d{1,2})(?:\/|\s)(\d{1,2})(?:\/|\s)(\d{2,4})$/

+0

Danke für die Mühe Kumpel. Nicht sicher, warum Sie nach unten gewählt wurden. Ich denke, meine einzige Kritik an dieser Methode ist, dass es sehr spezifisch ist angesichts der Natur möglicher Eingaben - aber das ist mein Problem, ich bin mir sicher, dass dies ein generischer Code ist, den Sie in Ihrer Toolbox für Probleme mit konsistenteren Eingaben herumliegen haben. Meine Antwort ähnelt Ihrer, indem ich versuche, mit Regex zu arbeiten. Aber anstatt ein formatiertes Spiel zurückzusenden, konvertiere ich einfach meine australische Saite in das US-Format. –

+0

Auch für die Person, die abgelehnt wird ... würde mich interessieren, warum? Nicht Trolling, ich wäre nur interessiert zu wissen - Ich könnte etwas lernen :) –

+0

Ja, es verlässt sich auf ein Format, außer es kam von einer Hilfsfunktion, die ich schrieb, dass nur das eine Format gegeben ist. Im obigen Beispiel gebe ich keine formatierte Übereinstimmung zurück, sondern eine Unixzeit von dem Datum, das einmal als ISO-Standard übergeben wurde (dasselbe MySQL verwendet, und PHP kann leicht in 'strtotime()' verwendet werden). Ich bin mir nicht sicher, ob es sich um einen Downvote handelt, vielleicht weil ich eine Regex verwendet habe, wenn einige Leute "explode()" bevorzugen würden. – alex

0
$date = date_create_from_format('d/m/Y', $date_string); 
$unix_timestamp = $date->getTimestamp(); 

oder

$date = DateTime::createFromFormat('d/m/Y', $date_string); 
$unix_timestamp = $date->getTimestamp(); 
0

Für zukünftige Leser, versuchen Sie die folgenden für die Zeit vom unstrusted Benutzereingabe Parsen, für die strptime() zu starr ist. Es gibt ISO-Datumszeichenfolgen aus, die Sie an new Date(), strtotime() usw. übergeben können, oder false für ungültige Daten oder null für keine verwendbare Eingabe. Sie müssten es an die Prozesszeiten anpassen. Es akzeptiert auch eine zweistellige Jahres- und ISO-Datumseingabe.

function parseUserDate($input, $allow_zero = false) { 
    if (!is_string($input)) { 
     return $input === null ? null : false; 
    } 
    $input = preg_split('/\\D+/', $input, null, PREG_SPLIT_NO_EMPTY); 
    if (!$input) { 
     return null;# no date 
    } 
    if (count($input) == 3) { 
     list($od, , $oy) = $input; 
     if (strlen($od) > 2 && strlen($oy) < 3) {# assume ISO 
      $oy = $od; 
      $input = array_reverse($input); 
     } 
     $intify = function($dig) { 
      return (int) ltrim($dig, '0');# prevent octals 
     }; 
     list($d, $m, $y) = array_map($intify, $input); 
     if (strlen($oy) < 3) { 
      $current_year = date('Y'); 
      $current_year_2 = $intify(substr($current_year, -2)); 
      $diff = $y - $current_year_2; 
      if ($diff > 50) { 
       $diff -= 100; 
      } 
      elseif ($diff < -50) { 
       $diff += 100; 
      } 
      $y = $diff + $current_year; 
     } 
     if (
      ($allow_zero && $d == 0 && $m == 0 && $y == 0) 
      || checkdate($m, $d, $y)# murrican function 
     ) { 
      return sprintf('%04d-%02d-%02d', $y, $m, $d); 
     } 
    } 
    return false;# invalid date 
}