我有一个列表,列出了给定年份的工作日(周一至周日为1-7)和星期数。我需要将该信息转换为给定日期。
因此,我编写了一个简单的脚本,该脚本包含三个参数: 1年 2.平日 3.周数
然后找出日期。
我的脚本基本上在给定年份的所有日期中进行迭代,并创建一个datetime对象,然后在其中提取isocalendar()[1]以将其与周数进行比较。
我发现如果输入2017 7 52,我将得到两个输出!
这是最基本的本质:
#!/Library/Frameworks/Python.framework/Versions/3.7/bin/python3
import datetime
def print_dt(year, month, day):
dt = datetime.date(year, month, day)
print("%d-%d-%d (%d) -> week# %d" % (year, month, day, dt.weekday(), dt.isocalendar()[1]))
print_dt(2017, 1, 1)
print_dt(2017, 12, 31)
与输出相同:
Anibals-iMac:RPEG anibal$ ./findDate-fixed-date.py
2017-1-1 (6) -> week# 52
2017-12-31 (6) -> week# 52
那怎么可能?这意味着2017年的第52周有两天的第六天,即两个不同的星期日。这种情况导致我的脚本出现问题。
关于如何解决这个问题的任何想法?
我最初的问题是,我在YYYYMMDD中给出了事件,因此我需要按年份将它们按年分组。因此,我可以说X的事件发生在2017年的第4周。在上面的情况下,直到第52周都不起作用,因为有一种以上的YYYYMMDD解决方案。
答案 0 :(得分:0)
您正在混合使用ISO日历年和公历日历年。
日期2017-1-1
是ISO日历中2016年第52周的第7天。
ISO日历将ISO日历年的第一周定义为包含相应格里高利历年的第一个星期四的周。 1月1日至7日可能在任何地方。由于ISO用星期一= 1到星期日= 7的天数,这意味着在每个新年前后最多三天,公历日期和ISO日历年不一致。
2015年1月1日是星期四,因此,尽管在2014年12月,星期一,星期二和星期三才具有2015年ISO日历年。类似地,2016年1月7日是星期四,星期五是1月1日至2016年1月3日星期日。尽管在2016年,但ISO日历年为2015。
您的脚本似乎在阳历中度过了一年,在整个阳历年中的所有日期中进行迭代,并寻找与星期几和ISO周号相匹配的日期。您发现的是,这三个值(格里高利年份,ISO周编号ISO周几)不能唯一地标识日期。您的脚本需要考虑以下事实:ISO日历年和公历日历年并不总是在ISO日历年而不是公历日历年上达成一致和匹配。一种方法是:
dt.isocalendar()[0]
中。或者,您也可以完全避免使用ISO日历系统,而可以考虑以下内容:
def get_week_and_day(year, month, day):
wday_of_jan_1 = datetime.date(year, 1, 1).timetuple().tm_wday
daytuple = datetime.date(year, month, day).timetuple()
wday = daytuple.tm_wday
week = (daytuple.tm_yday - 1 + wday_of_jan_1) // 7 + 1
return (week, wday)
鉴于每年,每月和每天,这将返回一年中的某周和一周中的某天,其中几周从星期一开始(根据time.struct_time
),而第1周是一月的一周1个星期进入。星期通常最多增加53个星期,但是如果a年的12月31日是星期一(与2012年一样),则这一天将是第54周。
这可以通过使用date.timetuple()
方法来获取日期中的工作日和日期,以及该年1月1日的星期几来实现。在week
的计算中,我们:
daytuple.tm_yday
减去1,因此1月1日为0
,1月2日为1
,依此类推。< / li>
wday_of_jan_1
将是2,则从第1周开始的周一和周二将丢失,因此第一周将只有5天。这种方法还避免了循环计算全年的日期并对其进行计算。