1. 程式人生 > >python生成時間序列(date_range)

python生成時間序列(date_range)

val del pla pri 是否 結束時間 and 更多 minute

介紹

自己寫了一個用python內置模塊實現的生成時間序列的函數

支持自動推斷字符串到datetime的轉換, 但對格式有一定要求, 其它格式可手動指定格式化方式, 格式化方式與python內置格式化格式完全一致

支持輸出格式化

以下是方法的源代碼(python環境3.5以上, 沒做更多版本的支持, 需要的自己稍作調整即可)

源代碼

import re
import calendar
import datetime


class FormatError(ValueError):
    pass


class Date(object):
    @classmethod
    def date_range(cls, start=None, end=None, periods=None, freq=None, input_format=None, out_format=None):
        
""" 生成時間序列 :param start: 序列開始時間 :param end: 序列結束時間, 給定start時, 結束時間不包含end :param periods: int, 生成的時間序列長度 :param freq: 要生成時間序列的時間間隔 :param out_format: 是否輸出格式化後的字符串, 若要輸出可指定輸出格式. "%Y-%m-%d %H:%M:%S" :param input_format: 若start或end是字符串且無法自動推斷時間格式則需指定格式 :return: [date or date_str]
""" start = cls.str_to_date(start, input_format) end = cls.str_to_date(end, input_format) out = [] if start is None and end and periods: for i in range(periods-1): old, end = cls.date_replace(end, cls._freq(freq), mod="-") if
i == 0: out.append(old) out = [end] + out elif end is None and start and periods: for i in range(periods-1): old, start = cls.date_replace(start, cls._freq(freq), mod="+") if i == 0: out.append(old) out.append(start) elif periods is None and start and end: i = 0 while True: old, start = cls.date_replace(start, cls._freq(freq), mod="+") if i == 0: out.append(old) i += 1 if start < end: out.append(start) else: break else: raise ValueError("start, end, periods 須且只能指定其中兩個") if out_format is True: out = [str(i) for i in out] elif out_format is not None: out = [i.strftime(out_format) for i in out] return out @staticmethod def date_replace(date, freq=(0, )*6, mod="+"): timedelta = datetime.timedelta(days=freq[2], hours=freq[3], minutes=freq[4], seconds=freq[5]) if mod == "+": if sum(freq[:2]) == 0: old = date date = date + timedelta elif sum(freq[2:]) == 0: y = date.year + freq[0] + (date.month + freq[1] - 1) // 12 m = (date.month + freq[1] - 1) % 12 + 1 old = date.replace(day=calendar.monthrange(date.year, date.month)[1]) date = date.replace(year=y, month=m, day=calendar.monthrange(y, m)[1]) else: raise ValueError(" ‘年月‘ 不能同時和 ‘日時分秒‘ 作為間隔") elif mod == "-": if sum(freq[:2]) == 0: old = date date = date - timedelta elif sum(freq[2:]) == 0: y = date.year - freq[0] + (date.month - freq[1] - 1) // 12 m = (date.month - freq[1] - 1) % 12 + 1 old = date.replace(day=calendar.monthrange(date.year, date.month)[1]) date = date.replace(year=y, month=m, day=calendar.monthrange(y, m)[1]) else: raise ValueError(" ‘年月‘ 不能同時和 ‘日時分秒‘ 作為間隔") else: raise ValueError("mod值只能是 ‘+‘ 或 ‘-‘ ") return old, date @staticmethod def _freq(freq=None): """ 設置時間間隔 :param freq: "Y2m3d4H5M6S" 表示間隔 1年2月3日4時5分6秒 :return: [年, 月, 日, 時, 分, 秒] """ freq_ = [0] * 6 if freq is None: freq_[2] = 1 return freq_ for n, i in enumerate(["Y", "m", "d", "H", "M", "S"]): r = f((\d*){i}) s = re.search(r, freq) if s: freq_[n] = int(s.group(2)) if s.group(2) else 1 return freq_ @staticmethod def str_to_date(string, format_=None): """ 字符串轉時間, 默認自動推斷格式 :param string: 時間字符串 :param format_: 格式 :return: 對應的時間類型, 輸入非字符串則原值輸出 """ if not isinstance(string, str): return string if format_: return datetime.datetime.strptime(string, format_) s = re.match(r(\d{4})\D+(\d{1,2})\D+(\d{1,2})(?:\D+(\d{1,2}))?(?:\D+(\d{1,2}))?(?:\D+(\d{1,2}))?\D*$, string) if s: result = [int(i) for i in s.groups() if i] return datetime.datetime(*result) s = re.match(r(\d{4})\D*(\d{2})\D*(\d{2})\D*(\d{2})?\D*(\d{2})?\D*(\d{2})?\D*$, string) if s: result = [int(i) for i in s.groups() if i] return datetime.datetime(*result) else: raise FormatError("自動推斷失敗, 請指定format_")

使用方式

print(Date.date_range(datetime.datetime(2018, 9, 18), periods=10))
print()
print(Date.date_range(20180918, 2018-09-28))
print()
print(Date.date_range(end=20180927, periods=10))
print()
print(Date.date_range(20180918, 2018-09-28, out_format=True))
print()
print(Date.date_range(2018/09/18, 2018-09-28, out_format="%Y-%m-%d"))
print()
print(Date.date_range(2018年9月18日, 2019-09-28, freq="m", out_format="%Y-%m-%d"))
print()
print(Date.date_range(2018/9/18, 2018-9-19, freq="3H", out_format=True))

對應結果

[datetime.datetime(2018, 9, 18, 0, 0), datetime.datetime(2018, 9, 19, 0, 0), datetime.datetime(2018, 9, 20, 0, 0), datetime.datetime(2018, 9, 21, 0, 0), datetime.datetime(2018, 9, 22, 0, 0), datetime.datetime(2018, 9, 23, 0, 0), datetime.datetime(2018, 9, 24, 0, 0), datetime.datetime(2018, 9, 25, 0, 0), datetime.datetime(2018, 9, 26, 0, 0), datetime.datetime(2018, 9, 27, 0, 0)]

[datetime.datetime(2018, 9, 18, 0, 0), datetime.datetime(2018, 9, 19, 0, 0), datetime.datetime(2018, 9, 20, 0, 0), datetime.datetime(2018, 9, 21, 0, 0), datetime.datetime(2018, 9, 22, 0, 0), datetime.datetime(2018, 9, 23, 0, 0), datetime.datetime(2018, 9, 24, 0, 0), datetime.datetime(2018, 9, 25, 0, 0), datetime.datetime(2018, 9, 26, 0, 0), datetime.datetime(2018, 9, 27, 0, 0)]

[datetime.datetime(2018, 9, 18, 0, 0), datetime.datetime(2018, 9, 19, 0, 0), datetime.datetime(2018, 9, 20, 0, 0), datetime.datetime(2018, 9, 21, 0, 0), datetime.datetime(2018, 9, 22, 0, 0), datetime.datetime(2018, 9, 23, 0, 0), datetime.datetime(2018, 9, 24, 0, 0), datetime.datetime(2018, 9, 25, 0, 0), datetime.datetime(2018, 9, 26, 0, 0), datetime.datetime(2018, 9, 27, 0, 0)]

[2018-09-18 00:00:00, 2018-09-19 00:00:00, 2018-09-20 00:00:00, 2018-09-21 00:00:00, 2018-09-22 00:00:00, 2018-09-23 00:00:00, 2018-09-24 00:00:00, 2018-09-25 00:00:00, 2018-09-26 00:00:00, 2018-09-27 00:00:00]

[2018-09-18, 2018-09-19, 2018-09-20, 2018-09-21, 2018-09-22, 2018-09-23, 2018-09-24, 2018-09-25, 2018-09-26, 2018-09-27]

[2018-09-30, 2018-10-31, 2018-11-30, 2018-12-31, 2019-01-31, 2019-02-28, 2019-03-31, 2019-04-30, 2019-05-31, 2019-06-30, 2019-07-31, 2019-08-31]

[2018-09-18 00:00:00, 2018-09-18 03:00:00, 2018-09-18 06:00:00, 2018-09-18 09:00:00, 2018-09-18 12:00:00, 2018-09-18 15:00:00, 2018-09-18 18:00:00, 2018-09-18 21:00:00]

python生成時間序列(date_range)