Awesome time conversion handling with support for chaining operations.
Project description
import copy import functools import logging import pickle import sys import threading import types import typing import re import time import datetime from dateutil.relativedelta import relativedelta import dateutil.parser import pytz import arrow
from pydantic import BaseModel
logger = logging.getLogger(name)
@functools.lru_cache() def get_localzone_ignore_version(): # python3.9以上不一样. tzlocal 版本在不同python版本上自动安装不同版本 from tzlocal import get_localzone try: return get_localzone().zone except AttributeError as e: return get_localzone().key
class DateTimeValue(BaseModel):
year: int
month: int
day: int
hour: int = 0
minute: int = 0
second: int = 0
microsecond: int = 0
class DateTimeValue: def init(self, year, month, day, hour=0, minute=0, second=0, microsecond=0): self.year = year self.month = month self.day = day self.hour = hour self.minute = minute self.second = second self.microsecond = microsecond
def dict(self):
return {
'year': self.year,
'month': self.month,
'day': self.day,
'hour': self.hour,
'minute': self.minute,
'second': self.second,
'microsecond': self.microsecond
}
class TimeInParamError(Exception): pass
class ArrowWrap(arrow.Arrow): def to_nb_time(self): return NbTime(self)
class NbTime: """ 时间转换,支持链式操作,纯面向对象的的。
相比模块级下面定义几十个函数,然后将不同类型的时间变量传到不同的函数中return结果,然后把结果作为入参传入到另一个函数进行转换,
纯面向对象支持链式转换的要方便很多。
初始化能够接受的变量类型丰富,可以传入一切类型的时间变量。
"""
FORMATTER_DATETIME = "%Y-%m-%d %H:%M:%S %z" # 2023-07-03 16:20:21 +0800 ,这种字符串格式的时间清晰明了没有时区的歧义.
FORMATTER_DATETIME_WITH_ZONE = "%Y-%m-%d %H:%M:%S %z"
FORMATTER_DATETIME_NO_ZONE = "%Y-%m-%d %H:%M:%S"
FORMATTER_MILLISECOND = "%Y-%m-%d %H:%M:%S.%f %z"
FORMATTER_DATE = "%Y-%m-%d"
FORMATTER_TIME = "%H:%M:%S"
FORMATTER_ISO = "%Y-%m-%dT%H:%M:%S%z" # iso8601,全球最标准的时间格式
TIMEZONE_UTC = 'UTC'
TIMEZONE_EASTERN_7 = 'UTC+7'
TIMEZONE_EASTERN_8 = 'UTC+8' # UTC+08:00 这是东八区
TIMEZONE_E8 = 'Etc/GMT-8' # 这个也是东八区,这个Etc/GMT是标准的pytz的支持的格式。
TIMEZONE_ASIA_SHANGHAI = 'Asia/Shanghai' # 就是东八区.
TIMEZONE_TZ_EAST_8 = datetime.timezone(datetime.timedelta(hours=8),
name='UTC+08:00') # 这种性能比pytz 'Asia/Shanghai' 性能高很多。但pytz可以处理历史夏令时。
TIMEZONE_TZ_UTC = datetime.timezone(datetime.timedelta(hours=0), name='UTC+07:00')
default_formatter: str = None
default_time_zone: str = None
@classmethod
def set_default_formatter(cls, datetime_formatter: str):
cls.default_formatter = datetime_formatter
@classmethod
def set_default_time_zone(cls, time_zone: str):
cls.default_time_zone = time_zone
@staticmethod
@functools.lru_cache()
def get_localzone_name() -> str:
zone = get_localzone_ignore_version()
print(f'auto get the system time zone is "{zone}"')
return zone
time_zone_str__obj_map = {}
def __init__(self,
datetimex: typing.Union[
None, int, float, datetime.datetime, str, 'NbTime', DateTimeValue, arrow.Arrow] = None,
*,
datetime_formatter: str = None,
time_zone: typing.Union[str, datetime.tzinfo, None] = None):
"""
:param datetimex: 接受时间戳 datatime类型 和 时间字符串 和类对象本身四种类型,如果为None,则默认当前时间now。
:param time_zone 时区例如 Asia/Shanghai, UTC UTC+8 GMT+8 Etc/GMT-8 等,也可以是 datetime.timezone(datetime.timedelta(hours=7))东7区,
默认是操作系统时区
"""
# init_params = copy.copy(locals())
# init_params.pop('self')
# init_params.pop('datetimex')
self._raw_in_params = {'datetimex':datetimex,'datetime_formatter':datetime_formatter,'time_zone':time_zone}
init_params = {'datetime_formatter': datetime_formatter, 'time_zone': time_zone}
self.init_params = init_params
self.first_param = datetimex
self.time_zone_str = self.get_time_zone_str(time_zone)
self.datetime_formatter = datetime_formatter or self.default_formatter or self.FORMATTER_ISO
'''
将 time_zone 转成 pytz 可以识别的对应时区
'''
self.time_zone_obj = self.build_pytz_timezone(self.time_zone_str)
self.datetime_obj = self.build_datetime_obj(datetimex)
self.datetime = self.datetime_obj
def _build_nb_time(self, datetimex) -> 'NbTime':
return self.__class__(datetimex, **self.init_params)
def get_time_zone_str(self, time_zone: typing.Union[str, datetime.tzinfo, None] = None):
return time_zone or self.default_time_zone or self.get_localzone_name()
def universal_parse_datetime_str(self, datetime_str):
try:
return dateutil.parser.parse(datetime_str)
except Exception as e:
date_string = datetime_str # "2013-05-05 12:30:45 America/Chicago"
date_parts = date_string.split()
parsed_date = dateutil.parser.parse(' '.join(date_parts[:-1]))
timezone = dateutil.tz.gettz(date_parts[-1])
datetime_obj = parsed_date.replace(tzinfo=timezone)
return self._build_nb_time(datetime_obj).datetime_obj
def build_datetime_obj(self, datetimex):
if datetimex is None:
# print(self.time_zone_obj,type(self.time_zone_obj))
datetime_obj = datetime.datetime.now(tz=self.time_zone_obj)
elif isinstance(datetimex, str):
# print(self.datetime_formatter)
if '%z' in self.datetime_formatter and ('+' not in datetimex or '-' not in datetimex):
datetimex = self.add_timezone_to_time_str(datetimex, self.time_zone_str)
try:
datetime_obj = datetime.datetime.strptime(datetimex, self.datetime_formatter)
except Exception as e:
# print(e,type(e))
# print(f'尝试使用万能时间字符串解析 {datetimex}')
logger.warning(f'warning! formatter: {self.datetime_formatter} cannot parse time str: {datetimex} , {type(e)} , {e} , will try use Universal time string parsing')
datetime_obj = self.universal_parse_datetime_str(datetimex)
# print(repr(datetime_obj))
if datetime_obj.tzinfo is None:
if isinstance(self.time_zone_obj, pytz.BaseTzInfo):
datetime_obj = self.time_zone_obj.localize(datetime_obj, )
else:
datetime_obj = datetime_obj.replace(tzinfo=self.time_zone_obj, )
else:
datetime_obj = datetime_obj.astimezone(self.time_zone_obj)
# if isinstance(self.time_zone_obj,pytz.BaseTzInfo) and datetime_obj.tzinfo is None:
# datetime_obj = self.time_zone_obj.localize(datetime_obj, )
# else:
# datetime_obj = datetime_obj.replace(tzinfo=self.time_zone_obj, )
# print(repr(datetime_obj))
elif isinstance(datetimex, (int, float)):
if datetimex < 1:
datetimex += 86400
if datetimex >= 10 ** 12:
# raise TimeInParamError(
# f'Invalid datetime param: {datetimex}. need seconds,not microseconds') # 需要传入秒,而不是毫秒
datetimex = datetimex / 1000.0
datetime_obj = datetime.datetime.fromtimestamp(datetimex, tz=self.time_zone_obj) # 时间戳0在windows会出错。
elif isinstance(datetimex, datetime.datetime):
datetime_obj = datetimex
datetime_obj = datetime_obj.astimezone(tz=self.time_zone_obj)
elif isinstance(datetimex, DateTimeValue):
datetime_obj = datetime.datetime(**datetimex.dict(), tzinfo=self.time_zone_obj)
elif isinstance(datetimex, NbTime):
datetime_obj = datetimex.datetime_obj
datetime_obj = datetime_obj.astimezone(tz=self.time_zone_obj)
elif isinstance(datetimex, arrow.Arrow):
datetime_obj = datetimex.datetime
datetime_obj = datetime_obj.astimezone(tz=self.time_zone_obj)
else:
raise ValueError('input parameters is not right')
return datetime_obj
@classmethod
def add_timezone_to_time_str(cls, datetimex: str, time_zone: str):
offset = cls.get_timezone_offset(time_zone)
offset_hour = int(offset.total_seconds() // 3600)
abs_offset_hour = abs(offset_hour)
int_timezone = ''
if abs_offset_hour < 10:
int_timezone = f'0{abs_offset_hour}00'
else:
int_timezone = f'{abs_offset_hour}00'
if offset_hour < 0:
int_timezone = f'-{int_timezone}'
else:
int_timezone = f'+{int_timezone}'
if not cls._contains_two_or_more_letters(datetimex):
datetimex += f' {int_timezone}'
return datetimex
@staticmethod
def _contains_two_or_more_letters(text):
pattern = r"[a-zA-Z]"
letters = re.findall(pattern, text)
return len(letters) >= 2
@classmethod
def get_timezone_offset(cls, time_zone: str) -> datetime.timedelta:
tz = cls.build_pytz_timezone(time_zone)
# 将时区转换为以Etc/GMT+形式表示的时区
offset = tz.utcoffset(datetime.datetime.now())
return offset
@staticmethod
def _utc_to_etc(timezone_str: str):
"""把UTC+8或UTC+08:00 转化成pytz可以识别的Etc/GMT-8的时区格式"""
offset_match = re.match(r"UTC([+-]?)(\d{1,2}):?(\d{0,2})", timezone_str)
if not offset_match:
return timezone_str
# 提取小时和分钟的偏移量
sign = offset_match.group(1)
hours = offset_match.group(2)
minutes = offset_match.group(3)
if sign == "+":
sign = "-"
else:
sign = "+"
# 构建新的时区表示
new_timezone = f"Etc/GMT{sign}{int(hours)}"
return new_timezone
@classmethod
def build_pytz_timezone(cls, time_zone: typing.Union[str, datetime.tzinfo]) -> datetime.tzinfo:
"""pytz 不支持 GTM+8 UTC+7 这种时区表示方式
Etc/GMT-8 就是 GMT+8 代表东8区。
"""
# print(time_zone,type(time_zone))
time_zone0 = time_zone
if time_zone0 in cls.time_zone_str__obj_map:
# print('zhijie')
return cls.time_zone_str__obj_map[time_zone0]
if isinstance(time_zone, datetime.tzinfo):
return time_zone
# 常见时区字符串转化为内置的timezone类型,比pytz性能高很多。
if time_zone in (cls.TIMEZONE_ASIA_SHANGHAI, cls.TIMEZONE_E8, cls.TIMEZONE_EASTERN_8):
# print('aaaa')
return cls.TIMEZONE_TZ_EAST_8
if time_zone in (cls.TIMEZONE_UTC, 'UTC+0'):
return cls.TIMEZONE_TZ_UTC
if 'Etc/GMT' in time_zone:
return pytz.timezone(time_zone)
# print(time_zone,type(time_zone))
time_zone = cls._utc_to_etc(time_zone)
# print(time_zone)
# pytz_timezone_xialinshi = pytz.timezone(time_zone)
pytz_timezone = pytz.timezone(time_zone, )
# print(pytz_timezone)
# # UTC 负时区对应的 pytz 可以识别的时区
# burden_timezone = 'Etc/GMT+'
# # UTC 正时区对应的 pytz 可以识别的时区
# just_timezone = 'Etc/GMT-'
# # 截取 UTC 时区差值,eg:zone_code=UTC+5,count=5
# count = time_zone[-1]
# if '-' in time_zone: # 就是这样没有反。
# pytz_timezone = pytz.timezone(burden_timezone + count)
# elif '+' in time_zone:
# pytz_timezone = pytz.timezone(just_timezone + count)
# else:
# pytz_timezone = pytz.timezone(time_zone)
cls.time_zone_str__obj_map[time_zone0] = pytz_timezone
return pytz_timezone
@property
def datetime_str(self) -> str:
return self.get_str()
@property
def time_str(self) -> str:
return self.datetime_obj.strftime(self.FORMATTER_TIME)
@property
def date_str(self) -> str:
return self.datetime_obj.strftime(self.FORMATTER_DATE)
def get_str(self, formatter=None):
# print(self.datetime_formatter)
return self.datetime_obj.strftime(formatter or self.datetime_formatter)
def fast_get_str_formatter_datetime_no_zone(self):
return f'{self.datetime_obj.year:04d}-{self.datetime_obj.month:02d}-{self.datetime_obj.day:02d} {self.datetime_obj.hour:02d}:{self.datetime_obj.minute:02d}:{self.datetime_obj.second:02d}'
@property
def timestamp(self) -> float:
return self.datetime_obj.timestamp()
@property
def timestamp_millisecond(self) -> float:
return self.datetime_obj.timestamp() * 1000
def is_greater_than_now(self) -> bool:
return self.timestamp > time.time()
def __lt__(self, other: 'NbTime'):
return self.timestamp < other.timestamp
def __gt__(self, other: 'NbTime'):
return self.timestamp > other.timestamp
def __eq__(self, other: 'NbTime'):
return self.timestamp == other.timestamp
def __str__(self) -> str:
return f'<NbTime [{self.datetime_str}] ({self.time_zone_str})>'
def __repr__(self) -> str:
return f'<NbTime [{self.datetime_str}] ({self.time_zone_str})>'
def humanize(self)->str:
return self.arrow.humanize()
def to_arrow(self)->ArrowWrap:
# return arrow.get(self.datetime_obj)
return ArrowWrap(year=self.datetime_obj.year, month=self.datetime_obj.month, day=self.datetime_obj.day,
hour=self.datetime_obj.hour,minute=self.datetime_obj.minute,second=self.datetime_obj.second,
microsecond=self.datetime_obj.microsecond,
tzinfo=self.time_zone_str)
@property
def arrow(self) -> ArrowWrap:
if getattr(self, '_arrow_obj', None) is None:
self._arrow_obj = self.to_arrow()
return self._arrow_obj
def isoformat(self, timespec: str = 'seconds') -> str:
"""
返回 ISO 8601 格式字符串
:param timespec: 'seconds', 'milliseconds', 'microseconds'
"""
return self.datetime_obj.isoformat(timespec=timespec)
def __call__(self) -> datetime.datetime:
return self.datetime_obj
def clone(self) -> "NbTime":
return self._build_nb_time(self.datetime_obj, )
def __copy__(self):
return self.clone()
# def __getstate__(self):
# # 自定义序列化时保存的状态
# state = self._raw_in_params
# return state
# def __setstate__(self, state):
# new_self = self.__class__(**state)
# self.__dict__.update(new_self.__dict__)
def shift(self, years=0, months=0, days=0, leapdays=0, weeks=0,
hours=0, minutes=0, seconds=0, microseconds=0, ) -> 'NbTime':
relativedeltax = relativedelta(years=years, months=months, days=days, leapdays=leapdays, weeks=weeks,
hours=hours, minutes=minutes, seconds=seconds,
microseconds=microseconds, )
new_date = self.datetime_obj + relativedeltax
# seconds_delta = seconds + minutes * 60 + hours * 3600 + days * 86400 + weeks * 86400 * 7
return self._build_nb_time(new_date, )
def replace(self, year=None,
month=None,
day=None,
hour=None,
minute=None,
second=None,
microsecond=None,
):
kw = copy.copy(locals())
kw.pop('self')
kw_new = {}
for k, v in kw.items():
if v is not None:
kw_new[k] = v
datetime_new = self.datetime_obj.replace(**kw_new)
return self._build_nb_time(datetime_new)
def to_tz(self, time_zone: str) -> 'NbTime':
init_params = copy.copy(self.init_params)
init_params['time_zone'] = time_zone
return self.__class__(self.timestamp, **init_params)
def to_utc(self):
return self.to_tz(self.TIMEZONE_UTC)
def to_utc8(self):
return self.to_tz(self.TIMEZONE_E8)
@property
def today_zero(self) -> 'NbTime':
now = datetime.datetime.now(tz=self.time_zone_obj)
today_zero_datetime = now.replace(hour=0, minute=0, second=0, microsecond=0)
return self._build_nb_time(today_zero_datetime, )
@property
def today_zero_timestamp(self) -> float:
# zero_ts = time.mktime(datetime.date.today().timetuple())
# return zero_ts
# # 获取当天零点时间
# today_start = self.time_zone_obj.localize(datetime.datetime(now.year, now.month, now.day, 0, 0, 0))
# # today_start =datetime.datetime(now.year, now.month, now.day, 0, 0, 0,tzinfo=self.time_zone_obj)
# # 将当天零点时间转换为时间戳
# timestamp = int(today_start.timestamp())
return self.today_zero.timestamp
@property
def same_day_zero(self) -> 'NbTime':
"""
获取时间对象对应的当天的该对象时区的0点的 NbTime对象
:return:
"""
same_day_zero_datetime = self.datetime_obj.replace(hour=0, minute=0, second=0, microsecond=0)
return self._build_nb_time(same_day_zero_datetime, )
@staticmethod
def seconds_to_hour_minute_second(seconds):
"""
把秒转化成还需要的时间
:param seconds:
:return:
"""
m, s = divmod(seconds, 60)
h, m = divmod(m, 60)
return "%02d:%02d:%02d" % (h, m, s)
class PopularNbTime(NbTime): @property def ago_1_days(self): return self.shift(days=-1)
@property
def ago_7_days(self):
return self.shift(days=-7)
@property
def ago_30_days(self):
return self.shift(days=-30)
@property
def ago_180_days(self):
return self.shift(days=-180)
@property
def ago_360_days(self):
return self.shift(days=-360)
@property
def ago_720_days(self):
return self.shift(days=-720)
class UtcNbTime(NbTime): default_time_zone = NbTime.TIMEZONE_UTC
class ShanghaiNbTime(NbTime): # default_time_zone = NbTime.TIMEZONE_ASIA_SHANGHAI default_time_zone = NbTime.TIMEZONE_TZ_EAST_8 default_formatter = NbTime.FORMATTER_DATETIME_NO_ZONE
class NowTimeStrCache: # 生成100万次当前时间字符串%Y-%m-%d %H:%M:%S仅需0.4秒. # 全局变量,用于存储缓存的时间字符串和对应的整秒时间戳 _cached_time_str: typing.Optional[str] = None _cached_time_second: int = 0
# 为了线程安全,使用锁。在极高并发下,锁的开销远小于每毫秒都进行时间格式化。
_time_cache_lock = threading.Lock()
@classmethod
def fast_get_now_time_str(cls, timezone_str: str = None) -> str:
"""
获取当前时间字符串,格式为 '%Y-%m-%d %H:%M:%S'。
通过缓存机制,同一秒内的多次调用直接返回缓存结果,极大提升性能。
适用于对时间精度要求不高(秒级即可)的高并发场景。
:return: 格式化后的时间字符串,例如 '2024-06-12 15:30:45'
"""
# timezone_str = timezone_str or FunboostCommonConfig.TIMEZONE
# 获取当前的整秒时间戳(去掉小数部分)
current_second = int(time.time())
# 如果缓存的时间戳与当前秒数一致,直接返回缓存的字符串。
if current_second == cls._cached_time_second:
return cls._cached_time_str
# 如果不一致,说明进入新的一秒,需要重新计算并更新缓存。
# 使用锁确保在多线程环境下,只有一个线程会执行更新操作。
with cls._time_cache_lock:
# 双重检查锁定 (Double-Checked Locking),防止在等待锁的过程中,其他线程已经更新了缓存。
if current_second == cls._cached_time_second:
return cls._cached_time_str
# 重新计算时间字符串。这里直接使用 time.strftime,因为它在秒级更新的场景下性能足够。
# 我们不需要像 Funboost 那样为每一毫秒的调用都去做查表优化。
now = datetime.datetime.now(tz=pytz.timezone(timezone_str))
cls._cached_time_str = now.strftime('%Y-%m-%d %H:%M:%S', )
cls._cached_time_second = current_second
return cls._cached_time_str
if name == 'main': import nb_log
"""
1557113661.0
'2019-05-06 12:34:21'
'2019/05/06 12:34:21'
NbTime(1557113661.0)()
"""
print(NbTime.get_localzone_name())
print(NbTime(time_zone='UTC+8').today_zero_timestamp)
print(NbTime(time_zone='UTC+7').datetime_obj)
print(NbTime(time_zone='UTC+8').datetime_str)
print(NbTime(time_zone='UTC+7').time_zone_obj)
print(NbTime.get_timezone_offset('Asia/Shanghai'))
# NbTime.set_default_formatter(NbTime.FORMATTER_MILLISECOND)
NbTime.set_default_time_zone('UTC+8')
# print(NbTime('2023-05-06 12:12:12'))
print(NbTime())
print(NbTime(datetime.datetime.now())) # 和上面等效
print(NbTime(1709192429))
print(NbTime('2024-02-26 15:58:21', datetime_formatter=NbTime.FORMATTER_DATETIME_NO_ZONE,
time_zone=NbTime.TIMEZONE_EASTERN_7).datetime)
print(NbTime(DateTimeValue(year=2022, month=5, day=9, hour=6), time_zone='UTC+7'))
print(NbTime(datetime.datetime.now(tz=pytz.timezone('Etc/GMT+0')), time_zone='UTC+8'))
print(NbTime().shift(months=1).shift(hours=-1))
print(NbTime(datetime_formatter=NbTime.FORMATTER_MILLISECOND).to_tz(time_zone='UTC+8').to_tz(time_zone='UTC+0'))
print(NbTime.get_timezone_offset(NbTime.get_localzone_name()).total_seconds())
print(NbTime(time_zone='UTC+7').today_zero_timestamp)
print(NbTime.seconds_to_hour_minute_second(450))
print(NbTime(time_zone=NbTime.TIMEZONE_ASIA_SHANGHAI).datetime.tzinfo)
print(NbTime(time_zone='UTC+8').time_zone_obj)
print(NbTime(time_zone='UTC+07:00').time_zone_obj)
print(NbTime(time_zone=datetime.timezone(datetime.timedelta(hours=7))))
print(
NbTime(NbTime('2024-02-29 07:40:34', time_zone='UTC+0', datetime_formatter=NbTime.FORMATTER_DATETIME_NO_ZONE),
time_zone='UTC+8', datetime_formatter=NbTime.FORMATTER_MILLISECOND).datetime_str
)
print(NbTime('2024-02-29 07:40:34', time_zone='UTC+7'))
print(NbTime(NbTime('2024-02-29 07:40:34', time_zone='UTC+7'), time_zone='UTC+8',
datetime_formatter=NbTime.FORMATTER_ISO).datetime_str)
print(NbTime('2024-02-29 07:40:34', time_zone='UTC+7').to_tz('UTC+8').to_tz('utc').to_utc().datetime_str)
print(NbTime().get_str('%Y%m%d'))
print(NbTime().today_zero)
print(NbTime().today_zero_timestamp)
print(NbTime().replace(day=10, ).to_tz('UTC+6'))
print(NbTime().shift(days=-7).timestamp_millisecond)
print(NbTime(1709283094))
print(NbTime(DateTimeValue(year=2023, month=7, day=5, hour=4, minute=3, second=2, microsecond=1))
> NbTime(DateTimeValue(year=2023, month=6, day=6, hour=4, minute=3, second=2, microsecond=1)))
print(NbTime(1727252278000))
print(PopularNbTime().ago_7_days.timestamp_millisecond)
print(UtcNbTime())
print(UtcNbTime().today_zero.timestamp_millisecond)
print(ShanghaiNbTime())
print(NbTime('20230506T010203.886 +08:00'))
print(NbTime('2023-05-06 01:02:03.886'))
print(NbTime('2023-05-06T01:02:03.886 +08:00'))
print(NbTime('20221206 1:2:3'))
print(NbTime('Fri Jul 19 06:38:27 2024'))
print(NbTime('2013-05-05 12:30:45 America/Chicago'))
print(NbTime('2013-05-05 12:30:45 America/Chicago').isoformat())
print(NbTime('Jun 12 2024 10:30AM'))
import arrow
# print(arrow.get("tomorrow at 3pm")) # 报错
# print(NbTime("tomorrow at 3pm"))
print(arrow.now().shift(hours=-3).shift(days=6).humanize())
print(arrow.now().shift(hours=-3).shift(days=6))
print(NbTime('2025-09-29 10:01:02').humanize())
print(NbTime('2025-09-29 10:01:02').isoformat('microseconds'))
print(NbTime(arrow.now(tz='utc+7')))
print(NbTime().arrow.floor('hour'))
print(NbTime().arrow.floor('day'))
print(NbTime().arrow.ceil('day').to_nb_time().timestamp) # nb_time 和 arrow 之间 无限链式转化
nbt6 = NbTime()
nbt6_pickled =pickle.dumps(nbt6)
print(nbt6_pickled)
nbt6_new = pickle.loads(nbt6_pickled)
print(nbt6_new)
print()
for i in range(1000000):
# ShanghaiNbTime(time_zone='Asia/Shanghai').get_str()
# ShanghaiNbTime(time_zone='UTC+8').get_str()
# datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
# NbTime(time_zone='Asia/Shanghai') # 3秒100万次
arrow.now(tz='Asia/Shanghai') # 20秒100万次
# datetime.datetime.now(tz=datetime.timezone(datetime.timedelta(hours=8)))
# NbTime().fast_get_str_formatter_datetime_no_zone()
# get_now_time_str_by_tz()
# ts = 1717567890 # 示例时间戳
# time_str = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(ts))
# datetime.datetime.now()#.strftime("%Y-%m-%d %H:%M:%S")
# NowTimeStrCache.fast_get_now_time_str('Asia/Shanghai')
print()
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nb_time-2.7.tar.gz.
File metadata
- Download URL: nb_time-2.7.tar.gz
- Upload date:
- Size: 11.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
58a194231849b92f533b126de622066597b73240d0dc786c7191b8745b9d5a60
|
|
| MD5 |
e16ab2be91a64fc452ff21a2a4b3db98
|
|
| BLAKE2b-256 |
d784df91846fe5bcb8770f3e2b607cffc3effd6b69cd974e81542c868bacc477
|
File details
Details for the file nb_time-2.7-py3-none-any.whl.
File metadata
- Download URL: nb_time-2.7-py3-none-any.whl
- Upload date:
- Size: 16.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a8f039f5c5869c5ff50665b2ec73bdab9b00436627aacad93f6710b13fe0f5a5
|
|
| MD5 |
b75a69377c5ccf30dd56538fe77e8a9c
|
|
| BLAKE2b-256 |
c265c4e8c3aa6bea8f8667899d5c1f991b3933dd2db9ad4e4f400fd786f72345
|