jtyoui.tools.times 源代码

#!/usr/bin/python3.7
# -*- coding: utf-8 -*-
# @Time  : 2019/4/24 17:29
# @Author: Jtyoui@qq.com
from jtyoui.data import chinese_mon_number, add_time
from jtyoui.decorators import warns
import re
import datetime
import time
import itertools
import copy
import calendar


[文档]class StringTime: """解析时间 >>> st = StringTime('二零零七年十月三十一号下午2点半') >>> print(st.find_times()) """ def __init__(self, sentence, date_str=None, date_format='%Y-%m-%d %H:%M:%S'): """传入一个字符串时间和现在时间 :param sentence: 字符串时间 :param date_str: 你认为的现在时间,不传默认是当前时间 :param date_format: 时间格式 """ self._sentence = sentence self._localtime = date_str if date_str else time.strftime(date_format) self.format = date_format self.local = time.strptime(self._localtime, self.format) self.re_year = r'(今年)|(明年)|(后年)|(昨年)|(前年)|(去年)|(\d+年)' self.re_mon = r'(上个?月)|(这个?月)|(下个?月)|(\d{0,2}本?月底?)|(\d*个?月以?后)' self.re_day = r'(今天)|(明天)|(后天)|(昨天)|(前天)|(\d+日)|(\d+号)|(\d*天\w?[后前])' self.re_week = r'(上个?周)|(下个?周)|(星期日)|(星期天)|(星期\d+)|(周\d+)' self.re_hour = r'(早上)|(下午)|(晚上)|(\d+点)' self.re_min = r'(\d+分)|(\d+点半)' self.re_sec = r'(\d+秒)' self.now_year = self.local.tm_year self.now_mon = self.local.tm_mon self.now_day = self.local.tm_mday self.now_week = self.local.tm_wday + 1 self.chinese_numerals = copy.deepcopy(chinese_mon_number) self.chinese_numerals.pop('十') self.add_time = add_time self.times = set() @property def sentence(self): return self._sentence @sentence.setter def sentence(self, sentence): self._sentence = sentence
[文档] def adds(self, x, fmt): add = datetime.datetime.strptime(self._localtime, self.format) + datetime.timedelta(days=x) self.now_year = add.year self.now_mon = add.month self.now_day = add.day self.now_week = add.isoweekday() return add.strftime(fmt)
[文档] def find(self, name): """根据名字来查找年月日 :param name: 填写年、月、日、号、来找对应的日期 """ if name == '年': flag = '%Y' re_ = self.re_year elif name == '月': flag = '%m' re_ = self.re_mon elif name == '日' or name == '号': flag = '%d' re_ = self.re_day elif name == '周': flag = '%d' re_ = self.re_week else: flag = None re_ = '' date_time, day, add = [], 0, 0 for d in re.findall(re_, self.sentence): for i in d: if i: if i in ['星期日', '星期天']: day = 7 - self.now_week elif '星期' in i and i[-1].isdigit(): week = int(i[-1]) day = week - self.now_week elif '周' in i and len(i) < 3: # 周三、周四等 if i[-1].isdigit(): week = int(i[-1]) day = week - self.now_week else: add = self.add_time[i] else: if i in self.add_time: date_time.append(self.adds(self.add_time[i], flag)) elif re.search(r'\d{1,2}个?月以?后', i): ds = int(i[0]) if i[0].isdigit() else int(i[0:2]) self.now_mon = self.now_mon + ds elif name in i and '底' not in i: # 判断不是xx月底 if i[:-1].isdigit(): date_time.append(i[:-1]) elif '月底' in i: # 处理xx月底 if i[0] == '本': days = calendar.monthrange(self.now_year, self.now_mon)[1] date_time.append(self.now_mon) self._sentence += f'{days}日' elif i[0].isdigit(): days = calendar.monthrange(self.now_year, int(i[0]))[1] date_time.append(int(i[0])) self._sentence += f'{days}日' else: # 既没有xx月也没有本月之类的。暂未考虑 pass elif add_time.get(i[1]): if i[0].isdigit(): date_time.append(self.adds(int(i[0]), flag)) if day != 0 or add != 0: if add == 0 and date_time: days = int(date_time[0]) + day date_time = [days] else: days = self.adds(day + add, flag) if int(days) >= self.now_day: date_time.append(days) else: date_time.append(days) return date_time, 1 return date_time if date_time else []
[文档] def find_hour(self): """找对应的小时""" hours = [] flag = 0 for d in re.findall(self.re_hour, self.sentence): for i in d: if i: if i == '早上': flag = 0 elif i == '下午': flag = 12 elif i == '晚上': flag = 12 else: if i[:-1].isdigit(): if int(i[:-1]) >= 12: hours.append(int(i[:-1])) else: hours.append(int(i[:-1]) + flag) else: hours.append(0) return hours if hours else []
[文档] def find_min(self): """找对应的分钟""" minute = [] for d in re.findall(self.re_min, self.sentence): for i in d: if i: if i[:-1].isdigit(): minute.append(int(i[:-1])) elif '半' in i: minute.append(30) return minute if minute else []
[文档] def find_sec(self): """找对应的秒钟""" second = [] for d in re.findall(self.re_sec, self.sentence): if d: if d[:-1].isdigit(): second.append(d[:-1]) return second if second else []
[文档] @warns('该类已经废除、废除时间2019年11月1日(19.10.28版本),请将StringTime类换成ParseTime类使用', DeprecationWarning) def find_times(self): """根据一句话来找对应的时间""" words = re.split(r'[,.,。、?!?!]', self.sentence) for sentences_ in words: if not sentences_: continue sentences = re.split(r'[到至-]', sentences_) t = re.findall('早上|下午|晚上', sentences[0]) if t and len(t) == 1: sentences = [_ if re.findall('早上|下午|晚上', _) else t[0] + _ for _ in sentences] flag_y, flag_m, flag_d = [], [], [] # 临时变量,存放左右连词的性质 for sentence in sentences: str_ = [self.chinese_numerals.get(s, s) for s in sentence] + [' '] # 加[' ']的原因保证index+1不会出现list索引溢出 string = '' if '十' in str_: for index, c in enumerate(str_): # 判断十在每个位置上的不同意义 if c == '十': if str_[index - 1].isdigit() and str_[index + 1].isdigit(): # 比如:二十一实际上十可以取空,变成21 c = '' elif str_[index - 1].isdigit() and (not str_[index + 1].isdigit()): # 比如:二十实际上十变成0,变成20 c = '0' elif not str_[index - 1].isdigit() and str_[index + 1].isdigit(): # 比如:十三实际上十变成1,变成13 c = '1' else: c = '10' # 其余情况十就变成10 string += c else: string = ''.join(str_) if re.search('[上下]个?周[1-6日]', string): string = string.replace('周', '周星期') self._sentence = string y = self.find('年') # 找到一句话中的年份 m = self.find('月') # 找到一句话中的月份 d = self.find('号') # 找到一句话中的天数 d = d + self.find('日') # 找到一句话中的天数 w = self.find('周') # 找到一句话中的天数 if isinstance(w, tuple): if m: m[0] = int(m[0]) + w[1] else: m = [self.now_mon + w[1]] d += d + w[0] else: d += d + w h = self.find_hour() # 找到一句话中的小时 mi = self.find_min() # 找到一句话中的分钟 sec = self.find_sec() # 找到一句话中的秒钟 if not (y or m or d or h or mi or sec): continue if not y: y = flag_y if not m: m = flag_m if not d: d = flag_d if h and not d: d = [self.now_day] flag_y, flag_m, flag_d = y, m, d for y_, m_, d_, h_, mi_, sec_ in itertools.zip_longest(y, m, d, h, mi, sec): if not y_ and m_: y_ = self.now_year if not m_ and d_: if not y_: y_ = self.now_year m_ = self.now_mon add_y, add_m = divmod(m_, 12) y_ += add_y m_ = add_m if not mi_: mi_ = '00' if not sec_: sec_ = '00' if not m_: self.times.add(f'{y_}') elif not d_: self.times.add(f'{y_}-{m_:0>2}') elif not h_: self.times.add(f'{y_}-{m_:0>2}-{d_:0>2}') else: self.times.add(f'{y_}-{m_:0>2}-{d_:0>2} {h_:0>2}:{mi_:0>2}:{sec_:0>2}') break times = sorted(self.times) self.times.clear() return times
if __name__ == '__main__': print('-----------------默认是当日期------------------') st = StringTime('二零零七年十月三十一号下午2点半') print(st.find_times()) # ['2007-10-31 14:30:00'] st.sentence = '下周星期一下午15点半开会' print(st.find_times()) # ['2019-07-08 15:30:00'] print('-----------------切换日期------------------') st = StringTime('下周星期一下午2点半开会', '2019-4-17 00:00:00') print(st.find_times()) # ['2019-04-22 14:30:00'] print('----------------多个时间-------------------') st = StringTime('今天下午3点开会到4点整到12楼大会议室开会。') print(st.find_times()) # ['2019-07-02 15:00:00', '2019-07-02 16:00:00'] print('----------------没有时间-------------------') st = StringTime('我要是不传时间呢?') print(st.find_times()) # [] print('---------------只有天数--------------------') st = StringTime('今天去北京,明天去哪里?') print(st.find_times()) # ['2019-07-02', '2019-07-03'] print('---------------跳断日期--------------------') st = StringTime('下周星期一下午2点半到4点开会') print(st.find_times()) # ['2019-07-08 14:30:00', '2019-07-08 16:00:00'] print('---------------非常间断日期--------------------') st = StringTime('明天下午2点半一直到下周星期五下午4点开会') print(st.find_times()) # ['2019-07-03 14:30:00', '2019-07-12 16:00:00'] print('---------------没有日期或者天数--------------------') st = StringTime('下午2点半开会') print(st.find_times()) # ['2019-07-03 14:30:00'] print('---------------*几个月以后--------------------') st = StringTime('请王鹏宇下个月1号下午3点上交财务报表') print(st.find_times()) # ['2019-08-01 15:00:00'] print('--------------几天之后--------------') st = StringTime('三天之后下午3点开会') print(st.find_times()) # ['2019-07-08 15:00:00'] print('--------------几月底--------------') st = StringTime('明年的2月底之前必须交报告,本月底吃饭') print(st.find_times()) # ['2019-07-31', '2020-02-28'] print('--------晚上-----------') st = StringTime('晚上11点20分') print(st.find_times()) print('--------下个周几-----------') st = StringTime('下个周2') print(st.find_times()) print('--------几个月以后的日期--------') st = StringTime('5个月后的明天') print(st.find_times())