Python一些可能用的到的函数系列122 ATimer2

发布时间:2024年01月24日

说明

由于时间处理在算网中起到了更重要的作用:不仅是进行时间计算,而是成为架构规范的一部分,因此需要对ATimer进行升级,成为一个基础依赖对象。

内容

1 设计

ATimer的作用更多的是进行即时计算,ATimer2将拓展为基础运行工具,带来的变化:

  • 1 静态参数固化。对象将设定一个固定的静态参数,而不是即时生成。
  • 2 对象化同时微服务化。既是对象,也是微服务。通过GlobalFunc进行统一调用
  • 3 更多周期。按秒、分钟、天、周、月、年构成更完整的偏移周期。

因为太阳历的偏差,导致了需要在闰年补一天,所以没办法进行简单的推算来计算时间。而且每个月还有大小月,规则会比较麻烦。

所以我想先通过推断生成一个基本时间轴,通过基本时间轴可以进行大致的定位,然后再通过推算来处理具体的时间。

所以第一步是生成基本时间轴,第二步是进行时间的对齐与推断。

每个月都有1号。

假设我们获得了每个月1号的时间戳,那么就可以进行时间推断了。生成这样一个字典就屏蔽了平闰年与大小月的差异。

{'1970-01': -28800.0,
 '1970-02': 2649600.0,
 '1970-03': 5068800.0,
 ...

1.1 字符转时间戳

标准时间格式为yy-mm-dd HH:MM:SS,例如 2000-01-01 00:00:00。

只要将年月目标分yymon提取出来,查表就可以得到其月基准时间戳 month_ts,剩下的天、时、分、秒可以按照固定规则映射 day_ts = day * 86400 + hour * 3600 + minute * 60 + seconds
一个合法的日期表达,其时间戳必然小于下一个月的基准时间戳。

当然,这个约束可以在标准时间格式转换时加以确认。

1.2 时间戳转字符

选择比时间戳小的最近一个月基准时间戳,获取年月基准时间戳。然后将当前时间戳与月基准时间戳取差值,这个差值按照固定规则推算出日,时,分,秒。对应的字符则为月基准字符 + 推算字符。

2 开发

从实用的角度出发,时间轴覆盖范围为1970~2970, 这样的范围属于足够用且轴长度不会太长的样子。

2.1 月基准日历

第一步需要推算按天的日历。

既然确定了年份,那么按照平闰年生成千年历。然后以第一天作为基准(可以在这里考虑时区差),按照86400递增获取每一天的时间戳。

然后将1号的部分抽取出来,就形成了月基准时间轴。容易知道这个轴大约是12000的长度,很小的尺寸。在具体计算时,还可以根据要面对的问题临时抽取更小的轴进行计算。

三个入参:基准年、偏移年和时区

生成千年的天列表

base_year = 1970
next_years = 1000
# 千年历的制作
ty_calendar = []
for some_year in list(range(base_year , base_year +next_years)):
    if is_ryear(some_year):
        day_list = b_list 
    else:
        day_list = a_list

    tem_day_list = ['%s-%s' % (some_year, some_day) for some_day in day_list ]
    ty_calendar = ty_calendar + tem_day_list

生成一个frame

# 日表
ty_frame = pd.DataFrame()
ty_frame['date'] = list(ty_s)
ty_frame['day'] = list(range(len(ty_frame)))
ty_frame['seconds'] = ty_frame['day']  * 86400
ty_frame['tz8_seconds'] = ty_frame['seconds']  - 8 * 3600

在这里插入图片描述
筛选后生成年月为基准的表

sel = ty_frame['date'].apply(lambda x: True if x.endswith('-01') else False)
ty_yymon_df = ty_frame[sel]

在这里插入图片描述
得到一个基于年月的有序字典

yymon_dict = cl.OrderedDict(zip(list(ty_yymon_df['date']),list(ty_yymon_df['tz8_seconds'])))

2.2 转换

2.2.1 将字符转为时间戳

# 分离月 + 日:时:分:秒
def depart_mon_ddhhmmss(dt_str):
    pos = dt_str.rfind('-')
    yymon = dt_str[:pos]+'-01'
    ddhhmmss = dt_str[pos+1:]
    return yymon, ddhhmmss

def ddhhmmss2s(dhms_str):
    _d, _hms = dhms_str.split()
    _h,_m,_s = _hms.split(':')
    return 86400*(int(_d)-1) + 3600 *(int(_h)) + 60 *(int(_m)) + int(_s)
# 1 字符转时间戳
some_str = '2023-01-24 17:44:44'
yymon, dhms = depart_mon_ddhhmmss(some_str)
ts = yymon_dict[yymon] + ddhhmmss2s(dhms)
1674553484

在这里插入图片描述

2.2.2 将时间戳转为字符

# 时间戳的轴,长度 12000
time_axis = np.array(list(yymon_dict.values()))
dt_axis = list(yymon_dict.keys())
pos= max(np.where(time_axis <= ts)[0])
base_dt = dt_axis[pos]
base_ts = time_axis[pos]
gap_ts = ts - base_ts

def gapts2day(some_ts):
    _d = some_ts//86400
    _res1 = some_ts % 86400
    _h = _res1 //3600
    _res2 =  _res1 % 3600
    _m = _res2 //60
    _s = _res2 % 60
    return "-{:02d} {:02d}:{:02d}:{:02d}".format( _d + 1,_h,_m,_s)

char_ts = base_dt[:7] + gapts2day(gap_ts)
'2023-01-24 17:44:44'

转换功能是最基础的功能,在大规模时间转换上,应该会有不错的表现,后续可以验证一下。就在时间戳的转换和还原上,用pandas的apply进行简单的函数并行调用进行实验。未来如果效率需要,是可以将要转换的列直接用矩阵方式进行计算的,这样会快很多。

下一个核心功能的就是偏移计算了,偏移计算分为两类:

  • 1 已知某一个时间,需要知道之前或者之后的时间。
  • 2 已知两个时间,需要知道他们之间的差距。

这部分先写到这里吧。

文章来源:https://blog.csdn.net/yukai08008/article/details/135648192
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。