2010-02-04 10 views
8

Ich bin kürzlich auf ein großes Problem gestoßen, da ich ein System habe, das die Kunden wöchentlich bezahlt.ISO-8601 Wochennummerierung vs "Outlook" Nummerierung in PHP

Wie wir alle wissen, hat ein Jahr 52 Wochen, und es gibt Standards dafür. Ich verwende PHP alias date ('W'), um die Wochennummer von einem Datum zu erhalten, das das gemäß dem Standard ISO-8601 berechnet.

Hier sind einige Referenzen:

Aber hier ist das Problem: Jahr 2009 hat 53 Wochen. Es scheint, dass durch den Gregorianischen Kalender innerhalb von 400 Jahren 71 Jahre 53 Wochen haben. Das ist eine Sache, die ich nicht wusste und wahrscheinlich auch viele nicht.

Laut Wikipedia:

2009-12-31 ist 2009-W53-4 (ISO Jahr 2009 hat 53 Wochen nach dem Gregorianischen Jahr 2009 hinaus, die mit Donnerstag beginnt und endet, an beiden Enden mit 3 Tage).

und die Datumsfunktion in PHP respektiert es vollständig.

Wenn Sie in MS Outlook schauen und den Wochentag in der Kalenderansicht anzeigen, wird er 52 Wochen lang erscheinen. 28 DEC 2009 bis 03 JAN 2010 Woche 1. Ist das ein anderer Standard? Der US-Standard oder so?

Wenn ja, warum kann PHP das nicht unterstützen? Hat jemand eine Funktion gemacht, die dies unterstützt?

Ist es richtig, 53 Wochen zu haben? Wir haben sowohl europäische als auch amerikanische Kunden.

+0

Interessante Frage. Ich stelle fest, dass Outlook eine Woche 53 in 2011 hat. Es sieht so aus, als ob "Woche 1" die erste Woche mit dem 1. Januar ist. Da Wochen am Sonntag oder Montag basierend auf einer Einstellung beginnen können, könnte es für andere auch anders sein Benutzer. –

+0

Ich habe es gerade versucht. In Outlook können Sie jeden Tag als Starttag für die Woche festlegen. Die Wochennummerierung beginnt dann mit der Woche, die den 1. Januar enthält. In Outlook stehen somit sieben verschiedene Nummerierungsschemas zur Verfügung. –

Antwort

4

Ich denke nicht, dass Sie hier ein Problem haben werden. Fakt ist, dass Sie einen internationalen Standard für das Formatieren und Zählen von Datum und Uhrzeit einhalten (ISO8601). Wenn Sie Kunden haben, die sich beschweren, verweisen Sie sie einfach auf den Standard.

Outlook Woche Nummerierung ist etwas entspricht dem folgenden:

$dummyWeek = floor((date('z') + (date('N') - 1))/7) + 1; 

Für Abrechnungszwecke, sind Sie besser dran ISO8601 als Standard. In der Tat, wenn Sie Ihre Steuern betrachten, die Sie dieses Jahr füllen werden, werden sie das letzte Geschäftsjahr als 53 Wochen lang beschreiben.

Das Problem mit der Outlook-Art zu zählen ist, dass eine Woche nicht garantiert wird, 7 Tage zu sein. Zum Beispiel, OW01-2010 ist von nur 2 Tagen kompromittiert: Fr Jan 1, Sat Jan 2. Das ist eine schrecklich kurze Abrechnungszeitraum für eine Woche.

ISO8601 Wochen sind garantiert 7 Tage lang, weshalb wir alle 4/5/6 Jahre eine Schaltwoche brauchen.

Welche eine dieser Optionen würden Sie bevorzugen:

  • ISO8601: 53 Wochen ab und zu haben, aber jeder einzelne von ihnen ist 7 Tage lang.
  • Outlook: 52/53 Wochen in einem Jahr nach dem Zufallsprinzip, aber zweimal pro Jahr für eine "halbe Woche" bezahlen müssen.
+0

Datum 'z' und 'N'? – nathanchere

5

Outlook folgt keiner Art von Standard für die Wochennummerierung. Es hat zwei Einstellungen, die die Wochennummerierung festlegen, die als "Erster Tag der Woche" und "Erste Woche des Jahres" bezeichnet werden.

Durch Einstellen von "Erster Tag der Woche" auf Montag und "Erste Woche des Jahres" auf "Erste 4-Tage-Woche" kann der ISO-Standard simuliert werden.

Jeder Benutzer muss diese Anpassung vornehmen, um dem ISO-Standard zu folgen.

Ich kenne keinen separaten US-Standard, und anscheinend tut Outlook auch nicht.

0

Es gibt mehr außerhalb der USA als im Inneren - und ISO 8601 wird wahrscheinlich außerhalb der USA häufiger verwendet als innen.

Die erste Aussage "Ein Jahr hat 52 Wochen" stimmt nur teilweise, wie Sie jetzt herausgefunden haben. In Bezug auf ISO Wochen, können Sie mit Woche 53 enden, wie in Wikipedia erwähnt. Sie können bis zu drei Tage des Jahres N + 1 in Woche 52 des Jahres N oder in Woche 53 des Jahres N haben. Sie können bis zu drei Tage des Jahres N-1 auch in Woche 1 des Jahres N haben. Und Sie müssen sowohl ISO 'Woche-Jahr' als auch 'Woche' bestimmen - denn wenn das Gregorianische Kalenderjahr N ist, kann das ISO-Wochen-Jahr das Jahr N-1 oder N + 1 sein (abhängig davon, welches Ende des Jahr, mit dem du arbeitest). Deshalb gibt es zum Beispiel separate Formatbezeichner ('% Y', '% y', '% g', '% G') in strftime() (aber beachten Sie, dass der POSIX-Standard denkt, dass Tage vor dem ersten Montag im Januar sind) in Woche 0 des laufenden Jahres, nicht in Woche 52 oder 53 des Vorjahres).

Es scheint keinen zuverlässigen "US-Standard" für "Woche" zu geben. Je nach verwendeter Software ergeben sich unterschiedliche Ergebnisse. Wenn Sie sich die Oracle Definition der Woche ansehen, dann sind die ersten sieben Tage des Jahres Woche 1; Sie haben 1 oder 2 Tage in Woche 53 am Ende des Jahres.

Siehe auch SO 274861 für eine Implementierung des ISO-Wochennummerncodes. Selbst wenn Sie nicht in der Sprache programmieren, sollte der Algorithmus leicht verständlich sein.

0

Nur ein Wort der Warnung, wenn Sie PHP verwenden, könnten Sie auch MySQL verwenden. MySQL tut nicht folgen ISO-8601 Woche Konventionen, aber schließt es genug, dass Sie vielleicht denken, dass es tut. Wie andere Leute über Outlook bemerken, ist es nicht wert, eine wackelige, nicht standardisierte Art der Berechnung von Wochennummern nachzuahmen.

2

Hier ist die Art, wie ich es gelöst habe. Hinweis: Ich Code in PHP, aber der Algorithmus in SQL implementiert ist der relevante Teil meines Codes unten. Beachten Sie auch, dass ich '2028-12-31' getrennt behandelt habe, weil es ein spezielles Datum ist, das 54 als Wochennummer angibt.

// generate an sql that calculates the outlook week of $date (until 2033) 
function sqlWeek ($date) { 
    $week = "if(". $date . " = '2028-12-31', 54, (week(" . $date . ", 0) + if((year(" . $date . ") - 1) in (2011, 2016, 2022, 2033), 0, 1)) MOD (if (year(". $date .") = 2028, 54, if((year(".$date.") - 1) in (2011, 2016, 2022, 2033), 53, 52))))"; 

    return "concat(if(char_length(".$week.") < 2, concat('0', ".$week."), ".$week."), '/', year($date))"; 
} 
+0

Bitte beachten Sie auch, dass ich "Woche ('2011-11-09', 0)" verwendet habe, was bedeutet, dass die Woche am Sonntag beginnt. Wenn es am Montag beginnt, sollten Sie "Woche ('2011-11-09', 1)" verwenden. – Amit