Python日期操作和wxpython简单界面

        在写报名表处理、分析的时候,我基友问我怎么在excel中统计一段日期内有几个周几周几周几,我说这似乎跟excel没啥关系吧?要不我给你写一个小程序,分别输入开始日期和结束日期,然后属于想要统计的周几,然后就出来统计结果,他说可以。

        因为设计到日期,可以用python的datetime包来计算比手动实现(还要分闰年)容易得多。

        首先通过input()获取键盘输入,将开始日期字符串存放在变量中,因为事先指定(跟基友说好)输入的格式为'xxxx.xx.xx'格式,即分隔符使用点,所以可以用以下函数将字符串格式转化为datetime格式:

start=datetime.datetime.strptime(start_date, '%Y.%m.%d')

        start_time即字符串,'%Y.%m.%d'为输入字符串的的日期格式。

        在得到datetime格式的开始日期和结束日期后,可以直接相减,得到timedelta格式时间差,并通过调用时间差的days元素得到int类型的值。由于设定日期开始和结束都是包括在内的,所以int类型的天数还需要+1操作:

number_of_day=(end-start).days+1#包括首尾

        这样得到的number_of_day为想要的int类型的天数。

        之后一次性输入想要统计的周几周几周几,用数字表示星期数,中间用空格或点隔开(现在想了想,似乎没必要这么要求,不隔开也可以),用split分割得到存放输入的多个单个星期数的list。(似乎也可以不用分隔符分割,也可以用数字匹配等方法)。

string=input('请一次性用小写数字数字输入想要统计的周几,中间用空格或者点隔开:\n')
string=re.split(' +|\.',string)#'.'转义为'\.' 多个不同长度的分隔符之间用'|'分割开

        之后是计算string中的每个数字对应的星期数出现了几次。首先取天数除以7的整数(number_of_day//7),即计算天数内包含几个整周,设为n,则可简化为每个星期数出现了n次,然后获得开始日期的星期数(start.weekday()+1),i从1开始遍历到天数除以7的余数(剩下不足一周的天数),从开始日期的星期数开始,获得这一天的星期数((which_day+i-1)%7+1)),累加至星期数对应的映射中,最后输出即可。

    name_map={'1':'Mon','2':'Tue','3':'Wed','4':'Thur','5':'Fri','6':'Sat','7':'Sun'}
    statistics=dict()
    number_of_week=number_of_day//7
    remain_day=number_of_day%7
    for s  in string:
        statistics[name_map[s]]=number_of_week
        
    
    which_day=start.weekday()+1
    for i in range(remain_day):
        name=name_map[str((which_day+i-1)%7+1)]
        if name in statistics:
            statistics[name]+=1
            
    for index in statistics:
        print(index+':'+str(statistics[index]))
        
    xof=input('结束')#防止打包成exe的显示完结果闪退

完整的程序如下:

###project 1
## 

import datetime
import re
while True:
    start_date=input('请输入开始日期:\n')
    if start_date=='0':
        break
    end_date=input('请输入结束日期:\n')
    start=datetime.datetime.strptime(start_date, '%Y.%m.%d')
    end=datetime.datetime.strptime(end_date, '%Y.%m.%d')
    number_of_day=(end-start).days+1#包括首尾
    print('包括开始日期和结束日期一共'+str(number_of_day)+'天\n')
    string=input('请一次性用小写数字数字输入想要统计的周几,中间用空格或者点隔开:\n')
    string=re.split(' +|\.',string)#'.'转义为'\.' 多个不同长度的分隔符之间用'|'分割开
    name_map={'1':'Mon','2':'Tue','3':'Wed','4':'Thur','5':'Fri','6':'Sat','7':'Sun'}
    statistics=dict()
    number_of_week=number_of_day//7
    remain_day=number_of_day%7
    for s  in string:
        statistics[name_map[s]]=number_of_week
        
    
    which_day=start.weekday()+1
    for i in range(remain_day):
        name=name_map[str((which_day+i-1)%7+1)]
        if name in statistics:
            statistics[name]+=1
            
    for index in statistics:
        print(index+':'+str(statistics[index]))
        
    xof=input('结束')

打包后如图:

但是我基友说验收不合格,不能修改时间段啥的,每次都要全打,很麻烦(拜托,你的要求没有这点好不好),但是修改开始日期结束日期在键盘操作下有点麻烦,于是用wx就给他整个界面吧!

首先创建app和框架frame:

import wx
app = wx.App()
frame = wx.Frame(None,title = "LCX Project 1",pos = (600,200),size = (500,500))

frame的参数pos表示左上角点在屏幕的相对位置,size为框架大小。由于重复运行会显示app已经创建,所以在最开始需要加如下操作:

if 'app' in locals():
    del app

即检测变量'app'是否在全局变量中,如果在,则del掉它。

在frame的指定位置(pos相对frame而言)添加静态文本,用来显示提示等,显示文本为label:

start_text=wx.StaticText(frame,label="请输入开始日期:",pos = (20,50))

在frame的指定位置添加文本框,用来用户输入文本,size为文本框的大小:

start_date = wx.TextCtrl(frame,pos = (120,45),size = (200,30))

在frame的指定位置添加按钮,用来调用自定义函数:

change_start = wx.Button(frame,label = "修改",pos = (350,45),size = (50,30))

并绑定按钮点击函数到自定义函数change_start_f上:

def change_start_f():
    ...
...
change_start.Bind(wx.EVT_BUTTON,change_start_f)

这样,当图形界面的change_start按钮被点击后会执行change_start_f函数。

把之前键盘输入的星期数改为了多选框,生成7个多选框并放入列表checkbox中,name_map储存每个数字对应的星期数。

name_map={'1':'Mon','2':'Tue','3':'Wed','4':'Thur','5':'Fri','6':'Sat','7':'Sun'}
checkbox=list()
for i in range(7):
    checkbox.append(wx.CheckBox(frame, -1, name_map[str(round(i+1))], pos=(30+50*i, 300)))

在最后添加两行代码以确保界面的显示和运行。

frame.Show()
app.MainLoop()

被绑定的开始日期和结束日期右侧的按钮的点击函数如下:

def change_start_f(event):
    global start
    start=datetime.datetime.strptime(start_date.GetValue(), '%Y.%m.%d')
    show_start=wx.StaticText(frame,label=str(start),pos = (120,95))
def change_end_f(event):
    global end
    end=datetime.datetime.strptime(end_date.GetValue(), '%Y.%m.%d')
    show_end=wx.StaticText(frame,label=str(end),pos = (120,195))

global x:将x设为全局变量,可以被其他函数访问到,点击”修改“按钮后会将文本框start_date的输入值(start_date.GetValue()获得)写入全局变量start,并在文本框的下方显示start,end同理。

点击”显示结果“调用的函数:

def show_ans(event):
    number_of_day=(end-start).days+1
    string='包括开始日期和结束日期一共'+str(number_of_day)+'天\n'
    show_days=wx.StaticText(frame,label=string,pos = (20,400))
    statistics=dict()
    number_of_week=number_of_day//7
    remain_day=number_of_day%7
    for check in checkbox:
        if check.GetValue():
            statistics[check.GetLabel()]=number_of_week
    which_day=start.weekday()+1
    for i in range(remain_day):
        name=name_map[str((which_day+i-1)%7+1)]
        if name in statistics:
            statistics[name]+=1
    i=0     
    frame2=wx.Frame(None,title = "Ans",pos = (600,200),size = (200,300))
    for index in statistics: 
        string=index+':'+str(statistics[index])
        wx.StaticText(frame2,label=string,pos = (20,30*i))
        i+=1
    frame2.Show()

大部分内容和之前黑框版本内容相似,其中通过遍历调用列表checkbox的每一个check的GetValue()函数判断对应的多选框是否打勾(打勾的话会返回True,否则False)来将每一个打勾的框的显示名(check.GetLabel())放入字典staticstics中并映射到完整的周数。其他操作相同。

由于多次执行时之前的结果仍保留在frame上(比如第一次显示周一周二周三,第二次显示周四周五时,周一周二会被第二次的覆盖掉,但没有被覆盖掉的周三会继续显示),所以直接再新建一个frame2然后将结果显示在里边就好了!哈哈哈的,多么不求甚解。

完整代码:

# -*- coding: utf-8 -*-
"""
Created on Mon Nov 18 14:50:29 2019

@author: 71405
"""
import datetime
if 'app' in locals():
    del app
import wx
def change_start_f(event):
    global start
    start=datetime.datetime.strptime(start_date.GetValue(), '%Y.%m.%d')
    show_start=wx.StaticText(frame,label=str(start),pos = (120,95))
def change_end_f(event):
    global end
    end=datetime.datetime.strptime(end_date.GetValue(), '%Y.%m.%d')
    show_end=wx.StaticText(frame,label=str(end),pos = (120,195))
def show_ans(event):
    number_of_day=(end-start).days+1
    string='包括开始日期和结束日期一共'+str(number_of_day)+'天\n'
    show_days=wx.StaticText(frame,label=string,pos = (20,400))
    statistics=dict()
    number_of_week=number_of_day//7
    remain_day=number_of_day%7
    for check in checkbox:
        if check.GetValue():
            statistics[check.GetLabel()]=number_of_week
    which_day=start.weekday()+1
    for i in range(remain_day):
        name=name_map[str((which_day+i-1)%7+1)]
        if name in statistics:
            statistics[name]+=1
    i=0     
    frame2=wx.Frame(None,title = "Ans",pos = (600,200),size = (200,300))
    for index in statistics: 
        string=index+':'+str(statistics[index])
        wx.StaticText(frame2,label=string,pos = (20,30*i))
        i+=1
    frame2.Show()
app = wx.App()
frame = wx.Frame(None,title = "LCX Project 1",pos = (600,200),size = (500,500))
start_text=wx.StaticText(frame,label="请输入开始日期:",pos = (20,50))
start_text=wx.StaticText(frame,label="请输入结束日期:",pos = (20,150))
start_text=wx.StaticText(frame,label="请选择要统计的周几:",pos = (20,250))
start_date = wx.TextCtrl(frame,pos = (120,45),size = (200,30))
end_date = wx.TextCtrl(frame,pos = (120,145),size = (200,30))
change_start = wx.Button(frame,label = "修改",pos = (350,45),size = (50,30))
change_start.Bind(wx.EVT_BUTTON,change_start_f)  
change_end = wx.Button(frame,label = "修改",pos = (350,145),size = (50,30))
change_end.Bind(wx.EVT_BUTTON,change_end_f)   
name_map={'1':'Mon','2':'Tue','3':'Wed','4':'Thur','5':'Fri','6':'Sat','7':'Sun'}
show = wx.Button(frame,label = "显示结果",pos = (150,360),size = (100,30))
show.Bind(wx.EVT_BUTTON,show_ans)  
checkbox=list()
for i in range(7):
    checkbox.append(wx.CheckBox(frame, -1, name_map[str(round(i+1))], pos=(30+50*i, 300)))
    
frame.Show()
app.MainLoop()

打包运行效果:

猜你喜欢

转载自blog.csdn.net/qq_36614557/article/details/103139685