2016-12-05 98 views
1

,當我與返回日期字符串引用第53周爲一年的API時2016年紅寶石返回無效日期(錯誤DOW)解析日期字符串

我發現的唯一的日曆,工作時解析它是JULIAN

但是,Date.parse("2016-W53", true, Date::JULIAN)返回Mon, 27 Dec 2016,這是錯誤的日期,因爲它應該是Mon, 26 Dec 2016

這是怎麼發生的?
我怎樣才能得到它返回正確的日期?

回答

1

朱利安日曆是一個完全不同的日曆;在Julian日曆上,12/27 週一是,因爲在Julian日曆上,2016年1月1日是星期四,而在公曆上是星期五。

通常情況下,我會說使用Date.strptime('2016-W53','%G-W%V') ...但似乎不起作用。根據該文件,計算當年周的時候,Ruby的使用ISO 8601基於本週年和週數:

ISO 8601基於本週年和週數:
本週YYYY 1開頭一個星期一,包括YYYY-01-04。
第一週前一年的日子是去年的最後一週 。
%G - 以周爲週期的年份
%V - 以周爲基準的年份的週數(01..53)
%g - 以周爲基準年的最後2位數(00..99)

如上所述,本系統一年的第一週是包含1月4日的一週;在朱利安日曆中,第4日的週日被包含在1月1日的同一周;然而,在公曆中,第4個週一爲,因此標記爲2016年的「計數」的第一週 - 前一週爲2015年的第53周。

原因是(大概)不應該算一個星期爲2016年的第一週,也是2015年最後一週的;因爲如果你想要一段時間,比如10周,那麼你最終會在那一週計算兩次。之所以選擇1月4日作爲標記,原因可能是因爲如果1月1日這一週包括1月4日,那麼這7天的大部分時間將落在新的一年,所以這一週是新年的一部分。

鑑於上述情況, 2016年第53周,至少根據ISO規則計算週數。你可以實現你自己的系統來確定日期是什麼意思,但是你不得不問API的提供者你正在消費他們如何生成這些數字,否則你不知道你是否正確解釋它。

0

您不應該用Julian calendar來解釋日期,因爲它不能修正我們現在在西方國家使用的最近的Gregorian calendar中記錄的時間週期性「漂移」。

Date.parse應該工作,如果輸入的是有效的,它看起來像你的是不是:

Date.parse("2016-W53") 
# ArgumentError: invalid date 
Date.parse("2020-W53") 
# <Date: 2020-12-28 ((2459212j,0s,0n),+0s,2299161j)> 

我要說的是,如果默認標準庫中parse方法不能作出這樣的價值感,你應該寫你自己的解析器。上週

def custom_parse(str) 
    regex = /\A(?<year>\d{4})-W(?<week>\d{2})\z/ 
    if data = regex.match(str) 
    year = data[:year].to_i 
    week = data[:week].to_i 
    Date.commercial(year, week - 1) + 7 
    end 
end 

custom_parse("2016-W53") 
# <Date: 2017-01-02 ((2457756j,0s,0n),+0s,2299161j)> 
0

關於根據Wikipedia

如果12月31日是在週一,週二或週三,這是在明年01周。如果是在星期四,那是剛剛結束的第53周。如果在星期五它是在第52周(或53,如果剛剛結束的一年是閏年);如果在星期六或星期日,則在剛剛結束的第52周。

和:

它12月28日在裏面。因此最早可能的最早時間是從12月21日星期一延長到1月28日星期日,最新的可能性從12月28日星期一延續到1月3日(下一個陽曆年)。

因此,如果您想查看一年中有多少周,那麼您可以請求YYYY-12-28的週數。如果你這樣做在Ruby中,它應該是這樣的:

2014.upto(2016) do |i| 
    date = Date.new(i, 12, 28) 
    puts "#{date} - in week #{date.cweek}" 
end 

# 2014-12-28 - in week 52 
# 2015-12-28 - in week 53 
# 2016-12-28 - in week 52 

正如你可以看到有沒有53周在2016年這樣你得到的日期可能是錯誤的。我建議聯繫您的API提供商,因爲我認爲推出自己的方法來處理這種情況並不明智。

如果你需要需要推出自己的解決方案,你可以用的東西,看起來像這樣(正則表達式從tompave的例子)去:

class MyCustomDateParser 
    FORMAT = /\A(?<year>\d{4})-W(?<week>\d{2})\z/ 

    def self.parse!(date) 
    raise ArgumentError, "invalid date" unless m = date.match(FORMAT) 
    Date.parse(date) 
    rescue ArgumentError => e 
    fail e unless m[2] == "53" 
    Date.parse("#{m[1]}-W52") 
    end 
end