共计 2102 个字符,预计需要花费 6 分钟才能阅读完成。
[Python 实践] 利用 python 实现的日期映射礼拜 X 的简单实现
2018 年 12 月 19 日
最近在处理分析数据的时候,突发奇想试着从用户离职的日期上判断是主动辞职还是被动解雇?数据的背景是美国某企业员工离职日期数据,根据美国常见的周薪 / 半月薪发放方式,初步假定主动辞职的人一般会选择拿到该周工资后离职,因此更倾向于后半周;而解雇则随时可以发生,然而发生在前半周的离职行为很大程度上推测是被动解雇。
日期转换程序思想
言归正传。
网上打开现成的日历程序可以方便地手动查找任意日期对应的信息,如礼拜几 / 阴历 / 风水信息 / 节日等;然而如果你有一个几千样本的用户离职日期,上述方法就不现实了,作为一个 Python Coder,想到即是做到,决定顺手写个映射日期到礼拜几的小模块。
主要思想
将日期转换成礼拜几有很多方法,但是核心都离不开下述几点知识:
总体思想是找到一个起始日期 Start_Date,然后计算查询日期 Map_Date 距离起始日期的偏移天数,然后 mod 7 即可;
计算需要知晓每年各个月份的天数,一三五七八十腊有 31 天是你应该基本知晓的常识,其余月份除了 2 月份外,都是 30 天;
2 月份的天数与闰年平年有关,凡是能够被 4 整除却不能被 100 整除的即为闰年,否则为平年
需要特别注意的是,计算日期偏移的时候是通过 mod 7 将所有的天数映射到了 0~6 之间(运算等同与除以 7 得到的余数集合),可以得到公式:
$$
Weekday_-index = [Weekday_-index(Start_-Date) + Count_-Deviation_-Days] mod 7
$$
大家可以想象一个宽度只有 7 的矩阵,Start_Date 作为起点累加偏移天数后,效果类似于按照宽度 7 进行一行行输入叠加,最终停止的位置即为 Map_Date 的礼拜时间索引。
下述代码以 2010 年与 2011 年为例,给出了两年每个月份的天数以及每年 1 月 1 日的礼拜日期,以此作为起点计算该年中任意一个日期的礼拜时间。
def Transfor_Date_2_Weekdays(date):
# date: 2010-01-02
# 静态数据
# 一年有 12 个月,其中:
#
# 一月,三月,五月,七月,八月,十月,十二月都有 31 天。
#
# 四月,六月,九月,十一月都是 30 天。
cnt_10year_days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
cnt_11year_days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
start_weekday_10 = 4 # 2010-01-01 是礼拜五
start_year_10 = 2010
start_month_10 = 1
start_day_10 = 1
start_weekday_11 = 5 # 2011-01-01 是礼拜六
start_year_11 = 2011
start_month_11 = 1
start_day_11 = 1
# 分析输入的日期对应的礼拜几
year = float(date[:4])
month = float(date[5:7])
day = float(date[8:])
cnt_days = 0 #相对于对应年的 1 月 1 日的偏移
if year == 2010:
print cnt_10year_days, ‘\n’
j = 0
while j < month – 1:
cnt_days += cnt_10year_days[j]
j += 1
continue
cnt_days += day
cnt_days -= 1 # 减去 1 月 1 日自身一天
#print date, ‘is from 2010-01-01’, cnt_days, ‘ 天 \n’
#print cnt_days % 7, ‘\n’
#print start_weekday_10, ‘\n’
weekday = (start_weekday_10 + cnt_days) % 7 + 1
print date, ‘response to weekday is ‘, weekday, ‘\n’
return weekday
if year == 2011:
# 需要以 2011-01-01 为起点
j = 0
while j < month – 1:
cnt_days += cnt_11year_days[j]
j += 1
continue
cnt_days += day
cnt_days -= 1 # 减去自身一天
print date, ‘is from 2011-01-01’, cnt_days, ‘ 天 \n’
print cnt_days % 7, ‘\n’
print start_weekday_11, ‘\n’
weekday = (start_weekday_11 + cnt_days) % 7 + 1
print date, ‘response to weekday is ‘, weekday, ‘\n’
return weekday
具体运行只需要一句代码:
weekday = Transfor_Date_2_Weekdays(Map_Date)
然后输入日期测试:
2010-02-28 response to weekday is 7.0 # 礼拜天 2010-05-19 response to weekday is 3.0 # 礼拜三
2011-09-12 response to weekday is 1.0 # 礼拜一
通过日历验证全部通过!