2010-02-04 57 views
8

我最近遇到了一個大問題,因爲我有一個每週向客戶付費的系統。ISO-8601周編號與PHP中的「Outlook」編號

衆所周知,一年有52周,並且有標準。我使用PHP又名日期('W')來獲取日期中的星期數,該日期根據標準ISO-8601進行計算。

這裏有一些參考:

但這裏有一個問題:2009年有53個星期。看來通過公元400年內的公曆有71年,有53周。這是我不知道的一件事,可能很多事情都不是這樣。

根據維基百科:

2009-12-31 2009年是-W53-4(ISO 2009年全年有53周,2009年擴大了西曆,開始與結束日,在兩端結束三天)。

和PHP中的日期函數完全尊重它。

如果您查看MS Outlook,並在日曆視圖中顯示星期幾,則將出現52周 考慮2009年12月28日至2010年1月3日第1周。這是另一個標準嗎?美國標準還是什麼?

如果是這樣,那麼爲什麼PHP不能支持它呢?有沒有人提供支持這個功能的功能?

有53周是否正確?我們有歐洲和美國的客戶。

+0

有趣的問題。我注意到Outlook在2011年有53周的時間。它看起來像是將「第一週」定義爲包含1月1日的第一週。由於周可以在週日或週一基於設置開始,因此實際上可能會因不同而有所不同用戶。 – 2010-02-04 18:16:53

+0

我剛試過。 Outlook將允許您選擇任何一天作爲星期開始日,而星期編號僅從包含Jan 1的那一週開始。因此Outlook中有七種不同的編號方案。 – 2010-02-04 18:19:05

回答

4

我不認爲你會有問題在這裏。事實是,您正在遵循日期和時間格式化和計數的國際標準(ISO8601)。如果您有任何抱怨的客戶,只需將他們引用至標準。

Outlook的周編號爲有些等同於以下:

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

爲了計費,你最好使用ISO8601作爲標準。事實上,如果你看看你今年要填補的稅款,他們會將上一個財政年度描述爲53周。

與Outlook的計數方式的問題是,一週不能保證是7天。例如,OW01-2010只有2天的損失:1月1日星期五,1月2日星期六。這是一個星期非常短的結算週期。

ISO8601周保證長達7天,這就是爲什麼我們每4/5/6年需要一個閏周的原因。

這些選項中的一個,你會喜歡哪:

  • ISO8601:在同時具有53週一次,但他們中的每一一個長7天。
  • Outlook:每年隨機抽取52/53周,但每半年需要支付兩次「半周」費用。
+0

日期'z'和'N'? – nathanchere 2014-09-12 08:08:41

5

Outlook不遵循任何星期編號標準。它有兩個確定星期編號的設置,分別稱爲「星期幾」和「第一個星期」。

通過將「星期幾」設置爲星期一和「第一個星期」到「第一個星期」,可以模擬ISO標準。

每個用戶必須進行此調整才能遵循ISO標準。

我知道沒有單獨的美國標準,顯然,Outlook也沒有。

0

美國以外的地區比美國還要多 - ISO 8601在美國以外的地區可能比在美國境內使用的要廣泛得多。正如你現在發現的那樣,「一年有52周」的初步陳述只是部分正確的。就ISO周而言,您可以在第53周結束,如維基百科中所述。您可以在N年的第52周或第N年的第53周獲得N + 1年的最多三天.N年的第1周也可以有最多三天的N-1年。您需要確定ISO「週年」以及「周」 - 因爲當公曆年爲N時,ISO週年可以是年N-1或N + 1(取決於哪一年你正在使用的一年)。這就是爲什麼在strftime()中有單獨的格式說明符('%Y','%y','%g','%G')(但請注意,POSIX標準認爲在1月的第一個星期一之前的幾天是在當年的第0周,而不是在前一年的第52或53周)。

「周」似乎沒有任何可靠的'美國標準'。取決於您使用的軟件,您會得到不同的結果。如果你看一週的定義Oracle,那麼今年的前七天是第一週;你在一年的53週末有1或2天。

另請參閱SO 274861以獲取ISO星期數字代碼的實現。即使你不用語言編碼,算法也應該容易理解。

0

只是警告一句話,如果您使用PHP,您可能也會使用MySQL。 MySQL確實不是按照ISO-8601周的慣例,但它足夠接近,你可能會認爲它的確如此。正如其他人正在關注Outlook一樣,試圖模仿計算週數的不規範的方式並不值得!

2

這是我解決它的方法。 注意:我使用PHP編碼,但在SQL中實現的算法是我的代碼的相關部分。另請注意,我分別處理'2028-12-31',因爲它是一個特殊的日期,它給出了54周的數字。

// 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

此外,請注意,我使用了「Week('2011-11-09',0)」,意思是星期一從星期天開始。如果從星期一開始,則應使用「Week('2011-11-09',1)」。 – Amit 2011-11-09 13:31:29