一、基础概念
- UTC time:世界标准时间
- 东N区的本地时间 = UTC time + N小时
- 西N区的本地时间 = UTC time - N小时
- epoch time:时间开始的起点(对Unix而言,epoch time为 1970-01-01 00:00:00 UTC)
- timestamp:时间戳(也称为Unix时间 或 POSIX时间)
- 时间戳是个差值,其值与时区无关
- 1970-01-01 00:00:00 UTC到现在经过的秒数
二、 获取时间戳的方法
-
方法一:time直接产生时间戳
import time timestamp1 = time.time() print(timestamp1) # 输出=> 1623238666.627778
-
方法二:time.struct_time转化为时间戳
import time struct_time_instance = time.localtime() print(struct_time_instance) # 输出=> time.struct_time(tm_year=2021, tm_mon=6, tm_mday=9, tm_hour=19, tm_min=46, tm_sec=12, tm_wday=2, tm_yday=160, tm_isdst=0) timestamp2 = time.mktime(struct_time_instance) print(timestamp2) # ==> 1623238666.0
-
方法三:datetime.datetime产生的时间转化为时间戳
from datetime import datetime today = datetime.today() print(today, type(today)) # 输出=> 2021-06-09 19:54:07.773130 <class 'datetime.datetime'> timestamp3 = datetime.timestamp(today) print(timestamp3) # 输出=> 1659592438.965032
三、时间戳转化为时间
3.1 time类
-
方法一:时间戳 => 时间字符串
import time local_time1 = time.ctime(1623238666) print(local_time1) # 输出=> Wed Jun 9 19:37:46 2021
-
方法二:时间戳 => struct_time对象
import time local_time2 = time.localtime(1623238666) print(local_time2, type(local_time2)) # 输出=> time.struct_time(tm_year=2021, tm_mon=6, tm_mday=9, tm_hour=19, tm_min=37, tm_sec=46, tm_wday=2, tm_yday=160, tm_isdst=0)
-
方法三: => utc时间(与当前时间差8个小时)东八区
import time utc_time1 = time.gmtime(1623238666) print(utc_time1) # 输出=> time.struct_time(tm_year=2021, tm_mon=6, tm_mday=9, tm_hour=11, tm_min=37, tm_sec=46, tm_wday=2, tm_yday=160, tm_isdst=0)
3.2 datetime类
-
方法四:时间戳 => datetime对象
from datetime import datetime local_time4 = datetime.fromtimestamp(1623238666) print(local_time4, type(local_time4)) # 输出=> 2021-06-09 19:37:46 <class 'datetime.datetime'>
-
方法五:时间戳 => utc时间
from datetime import datetime utc_time2 = datetime.utcfromtimestamp(1623238666) print(utc_time2, type(utc_time2)) # 输出=> 2021-06-09 11:37:46
四、格式化时间
-
方法一:时间字符串 => struct_time时间对象
import time time_str = '2021-6-9 20:20' struct_time1 = time.strptime(time_str, '%Y-%m-%d %H:%M') print(struct_time1) # 输出=> time.struct_time(tm_year=2021, tm_mon=6, tm_mday=9, tm_hour=20, tm_min=20, tm_sec=0, tm_wday=2, tm_yday=160, tm_isdst=-1)
-
方法二:struct_time时间对象 => 时间字符串
import time struct_time2 = time.localtime(1623238666) string_time1 = time.strftime('%Y-%m-%d %H:%M', struct_time2) print(string_time1) # =>2021-06-09 19:37
-
方法三:时间字符串 => datetime
import datetime time_str = "2022-08-04 13:51:18.877221" date_time = datetime.datetime.strptime(time_str, '%Y-%m-%d %H:%M:%S.%f')
五、获取当前时间
-
方法一:获取time.struct_time类型的时间
import time localtime = time.localtime(time.time()) print("本地时间为 :", localtime) # 输出 => time.struct_time(tm_year=2021, tm_mon=6, tm_mday=18, tm_hour=17, tm_min=24, tm_sec=9, tm_wday=4, tm_yday=169, tm_isdst=0)
-
方法二:获取字符串的时间
import time localtime = time.asctime(time.localtime(time.time())) print("本地时间为 :", localtime, type(localtime)) # => Thu Apr 7 10:29:13 2016
-
方法三:today() 获取datetime.datetime类型
from datetime import datetime localtime = datetime.today() print("本地时间为 :", localtime, type(localtime)) # =>2021-06-18 17:30:17.814116
-
方法四:now() 获取datetime.datetime类型
from datetime import datetime localtime = datetime.now() print("本地时间为 :", localtime, type(localtime)) # =>2021-06-18 17:31:34.655896
六、关于时间的封装的方法
- 包括的方法:
- 指定格式的时间字符串 => 时间戳
- 时间戳 => 指定格式的时间字符串
- 获取指定时间戳的星期
- 返回指定时间范围中,每一天的时间戳
- 获取以本月为中轴,跨度三个月的第一天和最后一天
- 获取上月第一天及当月最后一天
- 获取本月第一天和最后一天的时间戳(13位)
- 获取指定时间范围,经历的每个星期
- 获取两个月份之间的所有月份
- 根据时间字符串获取当月的月首和月末
- 根据时间,当天的数据:年,第几周,星期几
- 时间的转化:将秒转化为:w d m s 的格式
- 封装的方法:
import calendar import datetime import time from typing import Union import pandas as pd class TimesTool(object): start_date = None end_date = None date_format = '%Y-%m-%d' day_format = '%Y-%m-%d %H:%M:%S' month_format = '%Y-%m' @classmethod def to_timestamp(cls, time_text, time_format: str = None): """指定格式的时间字符串 => 时间戳""" if not isinstance(time_text, str): return time_text time_array = time.strptime(time_text, time_format if time_format else cls.date_format) timestamp = int(time.mktime(time_array)) * 1000 return timestamp @classmethod def to_format(cls, timestamp_param, time_format: str = None): """时间戳 => 指定格式的时间字符串""" if len(str(timestamp_param)) == 13: timestamp_param = timestamp_param / 1000 time_array = time.localtime(timestamp_param) time_str = time.strftime(time_format if time_format else cls.date_format, time_array) return time_str @classmethod def format_utc(cls, time_text): try: time_text = list(time_text) time_text.insert(-2, ":") time_text = "".join(time_text) time_text = datetime.datetime.fromisoformat(time_text).strftime(cls.date_format) time_text = cls.to_timestamp(time_text) except ValueError: pass return time_text @classmethod def get_week(cls, timestamp): """获取13位时间戳,对应的星期。周一=0""" timestamp = timestamp / 1000 local_time = time.localtime(timestamp) date = time.strftime("%Y-%m-%d %H:%M:%S", local_time) week = datetime.datetime.strptime(date, "%Y-%m-%d %H:%M:%S").weekday() return week @classmethod def get_date_list(cls, begin_date, end_date): """返回指定时间范围中,每一天的时间戳 如:2023-07-01,2023-07-03,返回1号到3号时间戳(13位) """ date_list = [cls.to_timestamp(x.strftime(cls.date_format)) for x in list(pd.date_range(start=begin_date, end=end_date))] return date_list @classmethod def get_quarter_start_end(cls): """ 时间跨度3个月, 返回上个月的第一天,下个月的最后一天。如现在7月,返回('2023-06-01', '2023-08-31') """ if cls.start_date and cls.end_date: return cls.start_date, cls.end_date today = datetime.date.today() year = today.year month = today.month first_day_of_current_month = datetime.date(year, month, 1) last_month_last_day = first_day_of_current_month - datetime.timedelta(days=1) last_month_first_day = datetime.date(last_month_last_day.year, last_month_last_day. month, 1) days_num = calendar.monthrange(first_day_of_current_month.year, first_day_of_current_month.month)[1] next_month_first_day = first_day_of_current_month + datetime.timedelta(days=days_num) next_month_days = calendar.monthrange(next_month_first_day.year, next_month_first_day. month)[1] next_month_last_day = next_month_first_day + datetime.timedelta(days=next_month_days - 1) last_month_first_day = last_month_first_day.strftime(cls.date_format) next_month_last_day = next_month_last_day.strftime(cls.date_format) return last_month_first_day, next_month_last_day @classmethod def get_months_start_end(cls): """ 获取上月第一天及当月最后一天, :return: ('2023-06-01', '2023-07-31') """ if cls.start_date and cls.end_date: return cls.start_date, cls.end_date today = datetime.date.today() year = today.year month = today.month today = datetime.date.today() end_of_last_month = today - datetime.timedelta(today.day) last_month_start = datetime.date(end_of_last_month.year, end_of_last_month.month, 1). strftime(cls.date_format) _, day = calendar.monthrange(year, month) this_month_end = datetime.date(year, month, day).strftime(cls.date_format) return last_month_start, this_month_end @classmethod def get_two_months_start_end(cls): """获取之前到现在两个月的日期,两个月前第一天与当前月最后一天 返回('2023-05-01', '2023-07-31') """ today = datetime.date.today() year = today.year month = today.month current_month_first_day = datetime.date(year, month, 1) current_month_days = calendar.monthrange(year, month)[1] current_month_last_day = datetime.date(year, month, current_month_days) last_month_last_day = current_month_first_day - datetime.timedelta(days=1) last_month_first_day = datetime.date(last_month_last_day.year, last_month_last_day. month, 1) two_month_ago = last_month_first_day - datetime.timedelta(days=1) two_month_ago_first_day = datetime.date(two_month_ago.year, two_month_ago.month, 1) return two_month_ago_first_day.__str__(), current_month_last_day.__str__() @classmethod def get_current_month_start_end(cls): """获取本月第一天和最后一天的时间戳(13位)""" if cls.start_date and cls.end_date: return cls.to_timestamp(cls.start_date), cls.to_timestamp(cls.end_date) today = datetime.date.today() year = today.year month = today.month first_day_of_current_month = datetime.date(year, month, 1) days_num = calendar.monthrange(first_day_of_current_month.year, first_day_of_current_month.month)[1] last_day_of_current_month = first_day_of_current_month + datetime.timedelta (days=days_num - 1) first_day_stamp = cls.to_timestamp(str(first_day_of_current_month)) last_day_stamp = cls.to_timestamp(str(last_day_of_current_month)) return first_day_stamp, last_day_stamp @classmethod def get_today_stamp(cls): today_stamp = int(time.mktime(datetime.date.today().timetuple())) * 1000 return today_stamp @classmethod def get_data_list_week(cls, start_stamp: Union[int, float], end_stamp: Union[int, float]) -> list: """ 获取 开始时间到结束时间中,经历的每个星期 :param start_stamp 开始时间(时间戳) :param end_stamp 结束时间 """ start_date = cls.to_format(int(start_stamp), cls.date_format) end_date = cls.to_format(int(end_stamp), cls.date_format) data_list = cls.get_date_list(start_date, end_date) week_list = [] for date_item in data_list: week_list.append(cls.get_week(date_item)) return week_list @classmethod def every_month(cls, start: str, end: str) -> list: """ 给定开始时间、结束时间,获取每一个月份的月初与下个月的月初 :return: """ start = datetime.datetime.strptime(start, cls.date_format) end = datetime.datetime.strptime(end, cls.date_format) date_list = [] while start < end: temp = cls._add_months(start, 1) date_list.append(dict(start=start.strftime(cls.date_format), end=temp.strftime (cls.date_format))) start = temp return date_list @classmethod def get_between_month(cls, start_time: (int, str), end_time: (int, str), with_day: bool = False): """ 获取两个月份之间的所有月份:时间戳,-> ['2021-09', '2021-10', '2021-11', '2021-12'] :param start_time: 开始时间戳(13位时间戳或%Y-%m-%d格式) :param end_time: 结束时间戳(13位时间戳或%Y-%m-%d格式) :param with_day: 列表中的每一个月份是否具体到【天】,例如['2021-09-01', '2021-10-01'] :return: """ date_list = [] if isinstance(start_time, int): begin_date = datetime.datetime.strptime(cls.to_format(int(start_time), cls. month_format), cls.month_format) else: begin_date = datetime.datetime.strptime(start_time, cls.date_format) if isinstance(end_time, int): end_date = datetime.datetime.strptime(cls.to_format(int(end_time), cls. month_format), cls.month_format) else: end_date = datetime.datetime.strptime(end_time, cls.date_format) time_format = cls.month_format if not with_day else cls.date_format while begin_date <= end_date: date_str = begin_date.strftime(time_format) date_list.append(date_str) begin_date = cls._add_months(begin_date, 1) return date_list @classmethod def _add_months(cls, dt, months): month = dt.month - 1 + months year = dt.year + month // 12 month = month % 12 + 1 day = min(dt.day, calendar.monthrange(year, month)[1]) return dt.replace(year=year, month=month, day=day) @classmethod def get_start_end_stamp(cls, month_text, month_format: str = None): """ 根据时间字符串获取当月的月首和月末 :param month_text: 时间字符串 :param month_format: 时间格式化 :return: """ struct_time1 = time.strptime(month_text, month_format if month_format else cls. month_format) last_day = calendar.monthrange(struct_time1.tm_year, struct_time1.tm_mon)[1] month_start = str(datetime.date(struct_time1.tm_year, struct_time1.tm_mon, 1)) last_day_str = "{0}-{1}-{2} 23:59:59".format(struct_time1.tm_year, struct_time1. tm_mon, last_day) return cls.to_timestamp(month_start), cls.to_timestamp(last_day_str, cls.day_format) @classmethod def get_time_stamp_week_info(cls, time_text, is_end=False): """根据时间,当天的数据:年,第几周,星期几""" day_time_text = str(time_text).split(' ')[0] time_text = day_time_text + ' 23:59:59' if is_end else day_time_text + ' 00:00:00' time_stamp = cls.to_timestamp(str(time_text), cls.day_format) date_time = datetime.datetime.fromtimestamp(time_stamp / 1000) week_info = date_time.isocalendar() return time_stamp, date_time, week_info[0], week_info[1], week_info[2] @classmethod def get_times_until_current(cls, time_type: int = 0, start_date: int = None, end_date: int = None): """ 获取当月第一天到当天的数据 月的返回:[{'text':'2021-01','start_stamp':0,'end_stamp':1}] 周的返回:[{'text':'WEEK6','start_stamp':0,'end_stamp':1,'year':'2021'}] """ """ 1.设置start_date参数的作用:计算当月遗留未解决缺陷数时需要传入date_list, 而原本date_list是从2021-11开始计算,为了只在当前月更新,所以传入当前月的1号时间; 2.设置end_date参数的作用是:计算当月遗留未解决缺陷数时需要传入date_list,而计算date_list需 要起始时间和截止时间, 在手动执行扫描而不是定时扫描时,会传入错误的截止时间。例如在2022-08-05手动执行扫描2022-05-01 至2022-05-31范围的缺陷数据, 那date_list将会生成2022-05-01至2022-08-05的日期列表。 """ return_list = [] if not start_date or not end_date: start_stamp = TimesTool.to_timestamp('2021-11', cls.month_format) today_stamp = TimesTool.get_today_stamp() else: start_stamp = start_date today_stamp = end_date if time_type == 0: month_list = TimesTool.get_between_month(start_stamp, today_stamp) for month in month_list: start_stamp, end_stamp = TimesTool.get_start_end_stamp(month) month_item = {'text': month, 'start_stamp': start_stamp, 'end_stamp': end_stamp} return_list.append(month_item) else: start_text = TimesTool.to_format(start_stamp, cls.day_format) start_stamp, start_date, year, week_order, week = TimesTool. get_time_stamp_week_info(start_text) # 获取2021年第一周的开始 while year < 2021: start_date = start_date + datetime.timedelta(days=1) start_stamp, start_date, year, week_order, week = TimesTool. get_time_stamp_week_info(start_date) week_end_date = start_date + datetime.timedelta(days=7 - week) week_end_stamp, week_end_date, _, _, _ = TimesTool.get_time_stamp_week_info( week_end_date, True) week_item = {'text': 'WEEK{0}'.format(week_order), 'start_stamp': start_stamp, 'end_stamp': week_end_stamp, 'year': year} return_list.append(week_item) # 遍历获取到目前为止的每一周 while week_end_stamp < today_stamp: start_date = week_end_date + datetime.timedelta(days=1) start_stamp, start_date, year, week_order, week = TimesTool. get_time_stamp_week_info(start_date) week_end_date = start_date + datetime.timedelta(days=7 - week) week_end_stamp, week_end_date, _, _, _ = TimesTool.get_time_stamp_week_info( week_end_date, True) week_item = {'text': 'WEEK{0}'.format(week_order), 'start_stamp': start_stamp, 'end_stamp': week_end_stamp, 'year': year} return_list.append(week_item) return return_list @classmethod def check_time_in_the_same_month(cls, start: int, end: int): """ 判断两个时间戳是否在同一月,在同一月则返回为False,否则返回True。 :param start: 开始时间。 :param end: 结束时间。 :return: """ start_date = cls.to_format(start, '%Y%m') end_date = cls.to_format(end, '%Y%m') if start_date >= end_date: return False return True @classmethod def seconds_to_hour(cls, seconds: int): return cls.round(seconds / 60 / 60) @classmethod def covert_time(cls, seconds): """时间的转化:将秒转化为:w d m s 的格式 :param seconds: 时间,单位:秒 """ if seconds <= 0: return '' if seconds < 60: return f"{seconds}s " minute = int(seconds / 60) if minute < 60: time_str = f"{minute}m " time_str += TimesTool.covert_time(seconds - minute * 60) return time_str hour = int(minute / 60) if hour < 8: time_str = f"{hour}h " time_str += TimesTool.covert_time(seconds - hour * 3600) return time_str day = int(hour / 8) if day < 5: time_str = f"{day}d " time_str += TimesTool.covert_time(seconds - day * 28800) else: week = int(day / 5) time_str = f"{week}w " time_str += TimesTool.covert_time(seconds - week * 144000) return time_str