我正在使用api,它返回引用2016年第53周的日期字符串。
我发现解析它时唯一有效的日历是JULIAN
。
但是,Date.parse("2016-W53", true, Date::JULIAN)
会返回Mon, 27 Dec 2016
,这是错误的日期,因为它应该是Mon, 26 Dec 2016
。
为什么会发生这种情况? 如何让它返回正确的日期?
答案 0 :(得分: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 - 基于周的年份(00..99)的最后2位数
如上所述,本系统中一年的第一周是包含1月4日的一周;在朱利安历法中,星期日,第4天包含在1月1日的同一周;然而,在公历中,第4个是星期一,因此标志着2016年的第一周“重要” - 前一周是2015年的第53周。
原因是(大概)人们不应该计算一周是2016年的第一周,而也是 2015年的最后一周;因为如果你想要一段时间,比如10周,那么你最终会计算两周。选择1月4日作为标记的原因可能是因为如果1月1日这一周包括1月4日,那么7天的大部分时间都会在新的一年中落下,所以本周将成为新年的一部分。
鉴于上述情况, 2016年没有第53周,至少按照ISO规则计算周数。您可以实现自己的系统来确定日期的含义,但是您必须向API提供商询问他们如何生成这些数字,否则您将不知道您是否正确地解释了它
答案 1 :(得分: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)>
答案 2 :(得分: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
正如您所看到的,2016年没有53周,所以您获得的日期可能是错误的。我建议您联系您的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