pyxllib 0.0.43__py3-none-any.whl → 0.3.197__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyxllib/__init__.py +9 -2
- pyxllib/algo/__init__.py +8 -0
- pyxllib/algo/disjoint.py +54 -0
- pyxllib/algo/geo.py +541 -0
- pyxllib/{util/mathlib.py → algo/intervals.py} +172 -36
- pyxllib/algo/matcher.py +389 -0
- pyxllib/algo/newbie.py +166 -0
- pyxllib/algo/pupil.py +629 -0
- pyxllib/algo/shapelylib.py +67 -0
- pyxllib/algo/specialist.py +241 -0
- pyxllib/algo/stat.py +494 -0
- pyxllib/algo/treelib.py +149 -0
- pyxllib/algo/unitlib.py +66 -0
- pyxllib/autogui/__init__.py +5 -0
- pyxllib/autogui/activewin.py +246 -0
- pyxllib/autogui/all.py +9 -0
- pyxllib/autogui/autogui.py +852 -0
- pyxllib/autogui/uiautolib.py +362 -0
- pyxllib/autogui/virtualkey.py +102 -0
- pyxllib/autogui/wechat.py +827 -0
- pyxllib/autogui/wechat_msg.py +421 -0
- pyxllib/autogui/wxautolib.py +84 -0
- pyxllib/cv/__init__.py +1 -11
- pyxllib/cv/expert.py +267 -0
- pyxllib/cv/{imlib.py → imfile.py} +18 -83
- pyxllib/cv/imhash.py +39 -0
- pyxllib/cv/pupil.py +9 -0
- pyxllib/cv/rgbfmt.py +1525 -0
- pyxllib/cv/slidercaptcha.py +137 -0
- pyxllib/cv/trackbartools.py +163 -49
- pyxllib/cv/xlcvlib.py +1040 -0
- pyxllib/cv/xlpillib.py +423 -0
- pyxllib/data/__init__.py +0 -0
- pyxllib/data/echarts.py +240 -0
- pyxllib/data/jsonlib.py +89 -0
- pyxllib/{util/oss2_.py → data/oss.py} +11 -9
- pyxllib/data/pglib.py +1127 -0
- pyxllib/data/sqlite.py +568 -0
- pyxllib/{util → data}/sqllib.py +13 -31
- pyxllib/ext/JLineViewer.py +505 -0
- pyxllib/ext/__init__.py +6 -0
- pyxllib/{util → ext}/demolib.py +119 -35
- pyxllib/ext/drissionlib.py +277 -0
- pyxllib/ext/kq5034lib.py +12 -0
- pyxllib/{util/main.py → ext/old.py} +122 -284
- pyxllib/ext/qt.py +449 -0
- pyxllib/ext/robustprocfile.py +497 -0
- pyxllib/ext/seleniumlib.py +76 -0
- pyxllib/{util/tklib.py → ext/tk.py} +10 -11
- pyxllib/ext/unixlib.py +827 -0
- pyxllib/ext/utools.py +351 -0
- pyxllib/{util/webhooklib.py → ext/webhook.py} +45 -17
- pyxllib/ext/win32lib.py +40 -0
- pyxllib/ext/wjxlib.py +88 -0
- pyxllib/ext/wpsapi.py +124 -0
- pyxllib/ext/xlwork.py +9 -0
- pyxllib/ext/yuquelib.py +1105 -0
- pyxllib/file/__init__.py +17 -0
- pyxllib/file/docxlib.py +761 -0
- pyxllib/{util → file}/gitlib.py +40 -27
- pyxllib/file/libreoffice.py +165 -0
- pyxllib/file/movielib.py +148 -0
- pyxllib/file/newbie.py +10 -0
- pyxllib/file/onenotelib.py +1469 -0
- pyxllib/file/packlib/__init__.py +330 -0
- pyxllib/{util → file/packlib}/zipfile.py +598 -195
- pyxllib/file/pdflib.py +426 -0
- pyxllib/file/pupil.py +185 -0
- pyxllib/file/specialist/__init__.py +685 -0
- pyxllib/{basic/_5_dirlib.py → file/specialist/dirlib.py} +364 -93
- pyxllib/file/specialist/download.py +193 -0
- pyxllib/file/specialist/filelib.py +2829 -0
- pyxllib/file/xlsxlib.py +3131 -0
- pyxllib/file/xlsyncfile.py +341 -0
- pyxllib/prog/__init__.py +5 -0
- pyxllib/prog/cachetools.py +64 -0
- pyxllib/prog/deprecatedlib.py +233 -0
- pyxllib/prog/filelock.py +42 -0
- pyxllib/prog/ipyexec.py +253 -0
- pyxllib/prog/multiprogs.py +940 -0
- pyxllib/prog/newbie.py +451 -0
- pyxllib/prog/pupil.py +1197 -0
- pyxllib/{sitepackages.py → prog/sitepackages.py} +5 -3
- pyxllib/prog/specialist/__init__.py +391 -0
- pyxllib/prog/specialist/bc.py +203 -0
- pyxllib/prog/specialist/browser.py +497 -0
- pyxllib/prog/specialist/common.py +347 -0
- pyxllib/prog/specialist/datetime.py +199 -0
- pyxllib/prog/specialist/tictoc.py +240 -0
- pyxllib/prog/specialist/xllog.py +180 -0
- pyxllib/prog/xlosenv.py +108 -0
- pyxllib/stdlib/__init__.py +17 -0
- pyxllib/{util → stdlib}/tablepyxl/__init__.py +1 -3
- pyxllib/{util → stdlib}/tablepyxl/style.py +1 -1
- pyxllib/{util → stdlib}/tablepyxl/tablepyxl.py +2 -4
- pyxllib/text/__init__.py +8 -0
- pyxllib/text/ahocorasick.py +39 -0
- pyxllib/text/airscript.js +744 -0
- pyxllib/text/charclasslib.py +121 -0
- pyxllib/text/jiebalib.py +267 -0
- pyxllib/text/jinjalib.py +32 -0
- pyxllib/text/jsa_ai_prompt.md +271 -0
- pyxllib/text/jscode.py +922 -0
- pyxllib/text/latex/__init__.py +158 -0
- pyxllib/text/levenshtein.py +303 -0
- pyxllib/text/nestenv.py +1215 -0
- pyxllib/text/newbie.py +300 -0
- pyxllib/text/pupil/__init__.py +8 -0
- pyxllib/text/pupil/common.py +1121 -0
- pyxllib/text/pupil/xlalign.py +326 -0
- pyxllib/text/pycode.py +47 -0
- pyxllib/text/specialist/__init__.py +8 -0
- pyxllib/text/specialist/common.py +112 -0
- pyxllib/text/specialist/ptag.py +186 -0
- pyxllib/text/spellchecker.py +172 -0
- pyxllib/text/templates/echart_base.html +11 -0
- pyxllib/text/templates/highlight_code.html +17 -0
- pyxllib/text/templates/latex_editor.html +103 -0
- pyxllib/text/vbacode.py +17 -0
- pyxllib/text/xmllib.py +747 -0
- pyxllib/xl.py +39 -0
- pyxllib/xlcv.py +17 -0
- pyxllib-0.3.197.dist-info/METADATA +48 -0
- pyxllib-0.3.197.dist-info/RECORD +126 -0
- {pyxllib-0.0.43.dist-info → pyxllib-0.3.197.dist-info}/WHEEL +4 -5
- pyxllib/basic/_1_strlib.py +0 -945
- pyxllib/basic/_2_timelib.py +0 -488
- pyxllib/basic/_3_pathlib.py +0 -916
- pyxllib/basic/_4_loglib.py +0 -419
- pyxllib/basic/__init__.py +0 -54
- pyxllib/basic/arrow_.py +0 -250
- pyxllib/basic/chardet_.py +0 -66
- pyxllib/basic/dirlib.py +0 -529
- pyxllib/basic/dprint.py +0 -202
- pyxllib/basic/extension.py +0 -12
- pyxllib/basic/judge.py +0 -31
- pyxllib/basic/log.py +0 -204
- pyxllib/basic/pathlib_.py +0 -705
- pyxllib/basic/pytictoc.py +0 -102
- pyxllib/basic/qiniu_.py +0 -61
- pyxllib/basic/strlib.py +0 -761
- pyxllib/basic/timer.py +0 -132
- pyxllib/cv/cv.py +0 -834
- pyxllib/cv/cvlib/_1_geo.py +0 -543
- pyxllib/cv/cvlib/_2_cvprcs.py +0 -309
- pyxllib/cv/cvlib/_2_imgproc.py +0 -594
- pyxllib/cv/cvlib/_3_pilprcs.py +0 -80
- pyxllib/cv/cvlib/_4_cvimg.py +0 -211
- pyxllib/cv/cvlib/__init__.py +0 -10
- pyxllib/cv/debugtools.py +0 -82
- pyxllib/cv/fitz_.py +0 -300
- pyxllib/cv/installer.py +0 -42
- pyxllib/debug/_0_installer.py +0 -38
- pyxllib/debug/_1_typelib.py +0 -277
- pyxllib/debug/_2_chrome.py +0 -198
- pyxllib/debug/_3_showdir.py +0 -161
- pyxllib/debug/_4_bcompare.py +0 -140
- pyxllib/debug/__init__.py +0 -49
- pyxllib/debug/bcompare.py +0 -132
- pyxllib/debug/chrome.py +0 -198
- pyxllib/debug/installer.py +0 -38
- pyxllib/debug/showdir.py +0 -158
- pyxllib/debug/typelib.py +0 -278
- pyxllib/image/__init__.py +0 -12
- pyxllib/torch/__init__.py +0 -20
- pyxllib/torch/modellib.py +0 -37
- pyxllib/torch/trainlib.py +0 -344
- pyxllib/util/__init__.py +0 -20
- pyxllib/util/aip_.py +0 -141
- pyxllib/util/casiadb.py +0 -59
- pyxllib/util/excellib.py +0 -495
- pyxllib/util/filelib.py +0 -612
- pyxllib/util/jsondata.py +0 -27
- pyxllib/util/jsondata2.py +0 -92
- pyxllib/util/labelmelib.py +0 -139
- pyxllib/util/onepy/__init__.py +0 -29
- pyxllib/util/onepy/onepy.py +0 -574
- pyxllib/util/onepy/onmanager.py +0 -170
- pyxllib/util/pyautogui_.py +0 -219
- pyxllib/util/textlib.py +0 -1305
- pyxllib/util/unorder.py +0 -22
- pyxllib/util/xmllib.py +0 -639
- pyxllib-0.0.43.dist-info/METADATA +0 -39
- pyxllib-0.0.43.dist-info/RECORD +0 -80
- pyxllib-0.0.43.dist-info/top_level.txt +0 -1
- {pyxllib-0.0.43.dist-info → pyxllib-0.3.197.dist-info/licenses}/LICENSE +0 -0
pyxllib/basic/_2_timelib.py
DELETED
@@ -1,488 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
# -*- coding: utf-8 -*-
|
3
|
-
# @Author : 陈坤泽
|
4
|
-
# @Email : 877362867@qq.com
|
5
|
-
# @Data : 2020/09/20
|
6
|
-
|
7
|
-
|
8
|
-
import datetime
|
9
|
-
import math
|
10
|
-
import re
|
11
|
-
import time
|
12
|
-
import timeit
|
13
|
-
|
14
|
-
import arrow
|
15
|
-
|
16
|
-
from pyxllib.basic._1_strlib import shorten, natural_sort, listalign
|
17
|
-
|
18
|
-
____tictoc = """
|
19
|
-
基于 pytictoc 代码,做了些自定义扩展
|
20
|
-
|
21
|
-
原版备注:
|
22
|
-
Module with class TicToc to replicate the functionality of MATLAB's tic and toc.
|
23
|
-
Documentation: https://pypi.python.org/pypi/pytictoc
|
24
|
-
__author__ = 'Eric Fields'
|
25
|
-
__version__ = '1.4.0'
|
26
|
-
__version_date__ = '29 April 2017'
|
27
|
-
"""
|
28
|
-
|
29
|
-
|
30
|
-
class TicToc:
|
31
|
-
"""
|
32
|
-
Replicate the functionality of MATLAB's tic and toc.
|
33
|
-
|
34
|
-
#Methods
|
35
|
-
TicToc.tic() #start or re-start the timer
|
36
|
-
TicToc.toc() #print elapsed time since timer start
|
37
|
-
TicToc.tocvalue() #return floating point value of elapsed time since timer start
|
38
|
-
|
39
|
-
#Attributes
|
40
|
-
TicToc.start #Time from timeit.default_timer() when t.tic() was last called
|
41
|
-
TicToc.end #Time from timeit.default_timer() when t.toc() or t.tocvalue() was last called
|
42
|
-
TicToc.elapsed #t.end - t.start; i.e., time elapsed from t.start when t.toc() or t.tocvalue() was last called
|
43
|
-
"""
|
44
|
-
|
45
|
-
def __init__(self, title=''):
|
46
|
-
"""Create instance of TicToc class."""
|
47
|
-
self.start = timeit.default_timer()
|
48
|
-
self.end = float('nan')
|
49
|
-
self.elapsed = float('nan')
|
50
|
-
self.title = title
|
51
|
-
|
52
|
-
def tic(self):
|
53
|
-
"""Start the timer."""
|
54
|
-
self.start = timeit.default_timer()
|
55
|
-
|
56
|
-
def toc(self, msg='用时', restart=False):
|
57
|
-
"""
|
58
|
-
Report time elapsed since last call to tic().
|
59
|
-
|
60
|
-
Optional arguments:
|
61
|
-
msg - String to replace default message of 'Elapsed time is'
|
62
|
-
restart - Boolean specifying whether to restart the timer
|
63
|
-
"""
|
64
|
-
self.end = timeit.default_timer()
|
65
|
-
self.elapsed = self.end - self.start
|
66
|
-
print(f'{self.title} {msg} {self.elapsed:.3f} 秒.')
|
67
|
-
if restart:
|
68
|
-
self.start = timeit.default_timer()
|
69
|
-
|
70
|
-
def tocvalue(self, restart=False):
|
71
|
-
"""
|
72
|
-
Return time elapsed since last call to tic().
|
73
|
-
|
74
|
-
Optional argument:
|
75
|
-
restart - Boolean specifying whether to restart the timer
|
76
|
-
"""
|
77
|
-
self.end = timeit.default_timer()
|
78
|
-
self.elapsed = self.end - self.start
|
79
|
-
if restart:
|
80
|
-
self.start = timeit.default_timer()
|
81
|
-
return self.elapsed
|
82
|
-
|
83
|
-
@staticmethod
|
84
|
-
def process_time(msg='程序已启动'):
|
85
|
-
"""计算从python程序启动到目前为止总用时"""
|
86
|
-
print(f'{msg} {time.process_time():.3f} 秒')
|
87
|
-
|
88
|
-
def __enter__(self):
|
89
|
-
"""Start the timer when using TicToc in a context manager."""
|
90
|
-
self.start = timeit.default_timer()
|
91
|
-
|
92
|
-
def __exit__(self, *args):
|
93
|
-
"""On exit, print time elapsed since entering context manager."""
|
94
|
-
self.end = timeit.default_timer()
|
95
|
-
self.elapsed = self.end - self.start
|
96
|
-
print(f'{self.title} {self.elapsed:.3f} 秒.')
|
97
|
-
|
98
|
-
|
99
|
-
____timer = """
|
100
|
-
|
101
|
-
"""
|
102
|
-
|
103
|
-
|
104
|
-
def parse_perf(data):
|
105
|
-
""" 输出性能分析报告,data是每次运行得到的时间数组
|
106
|
-
"""
|
107
|
-
n, sum_ = len(data), sum(data)
|
108
|
-
|
109
|
-
if n > 1: # 有多轮,则应该输出些参考统计指标
|
110
|
-
# np有标准差等公式,但这是basic底层库,不想依赖太多第三方库,所以手动实现
|
111
|
-
mean = sum_ / n
|
112
|
-
std = math.sqrt((sum([(x - mean) ** 2 for x in data]) / n))
|
113
|
-
li = [f'总耗时: {sum_:.3f}s', f'均值标准差: {mean:.3f}±{std:.3f}s',
|
114
|
-
f'总数: {n}', f'最小值: {min(data):.3f}s', f'最大值: {max(data):.3f}s']
|
115
|
-
return '\t'.join(li)
|
116
|
-
elif n == 1: # 只有一轮,则简单地输出耗时即可
|
117
|
-
sum_ = sum(data)
|
118
|
-
return f'用时: {sum_:.3f}s'
|
119
|
-
else:
|
120
|
-
raise ValueError
|
121
|
-
|
122
|
-
|
123
|
-
class Timer:
|
124
|
-
"""分析性能用的计时器类,支持with语法调用
|
125
|
-
必须显示地指明每一轮的start()和end(),否则会报错
|
126
|
-
"""
|
127
|
-
|
128
|
-
def __init__(self, title=''):
|
129
|
-
"""
|
130
|
-
:param title: 计时器名称
|
131
|
-
"""
|
132
|
-
# 不同的平台应该使用的计时器不同,这个直接用timeit中的配置最好
|
133
|
-
self.default_timer = timeit.default_timer
|
134
|
-
# 标题
|
135
|
-
self.title = title
|
136
|
-
self.data = []
|
137
|
-
self.start_clock = float('nan')
|
138
|
-
|
139
|
-
def start(self):
|
140
|
-
self.start_clock = self.default_timer()
|
141
|
-
|
142
|
-
def stop(self):
|
143
|
-
self.data.append(self.default_timer() - self.start_clock)
|
144
|
-
|
145
|
-
def report(self, msg=''):
|
146
|
-
""" 报告目前性能统计情况
|
147
|
-
"""
|
148
|
-
msg = f'{self.title} {msg}'
|
149
|
-
n = len(self.data)
|
150
|
-
|
151
|
-
if n >= 1:
|
152
|
-
print(msg, parse_perf(self.data))
|
153
|
-
elif n == 1:
|
154
|
-
sum_ = sum(self.data)
|
155
|
-
print(f'{msg} 用时: {sum_:.3f}s')
|
156
|
-
else: # 没有统计数据,则补充执行一次stop后汇报
|
157
|
-
print(f'{msg} 暂无计时信息')
|
158
|
-
|
159
|
-
def __enter__(self):
|
160
|
-
return self
|
161
|
-
|
162
|
-
def __exit__(self, *args):
|
163
|
-
self.report()
|
164
|
-
|
165
|
-
|
166
|
-
def performit(title, stmt="pass", setup="pass", repeat=1, number=1, globals=None):
|
167
|
-
""" 在timeit.repeat的基础上,做了层封装
|
168
|
-
|
169
|
-
200920周日15:33,简化函数,该函数不再获得执行结果,避免重复运行
|
170
|
-
|
171
|
-
:param title: 测试标题、名称功能
|
172
|
-
:return: 返回原函数单次执行结果
|
173
|
-
"""
|
174
|
-
data = timeit.repeat(stmt=stmt, setup=setup, repeat=repeat, number=number, globals=globals)
|
175
|
-
print(title, parse_perf(data))
|
176
|
-
return data
|
177
|
-
|
178
|
-
|
179
|
-
def perftest(title, stmt="pass", repeat=1, number=1, globals=None, res_width=None, print_=True):
|
180
|
-
""" 与performit的区别是,自己手动循环,记录程序运行结果
|
181
|
-
|
182
|
-
:param title: 测试标题、名称功能
|
183
|
-
:param res_width: 运行结果内容展示的字符上限数
|
184
|
-
:param print_: 输出报告
|
185
|
-
:return: 返回原函数单次执行结果
|
186
|
-
|
187
|
-
这里为了同时获得表达式返回值,就没有用标注你的timeit.repeat实现了
|
188
|
-
"""
|
189
|
-
# 1 确保stmt是可调用对象
|
190
|
-
if callable(stmt):
|
191
|
-
func = stmt
|
192
|
-
else:
|
193
|
-
code = compile(stmt, '', 'eval')
|
194
|
-
|
195
|
-
def func():
|
196
|
-
return eval(code, globals)
|
197
|
-
|
198
|
-
# 2 原函数运行结果(这里要先重载stdout)
|
199
|
-
data = []
|
200
|
-
res = ''
|
201
|
-
for i in range(repeat):
|
202
|
-
start = time.time()
|
203
|
-
for j in range(number):
|
204
|
-
res = func()
|
205
|
-
data.append(time.time() - start)
|
206
|
-
|
207
|
-
# 3 报告格式
|
208
|
-
if res_width is None:
|
209
|
-
# 如果性能报告比较短,只有一次测试,那res_width默认长度可以高一点
|
210
|
-
res_width = 50 if len(data) > 1 else 200
|
211
|
-
if res is None:
|
212
|
-
res = ''
|
213
|
-
else:
|
214
|
-
res = '运行结果:' + shorten(str(res), res_width)
|
215
|
-
if print_:
|
216
|
-
print(title, parse_perf(data), res)
|
217
|
-
|
218
|
-
return data
|
219
|
-
|
220
|
-
|
221
|
-
class PerfTest:
|
222
|
-
""" 这里模仿了unittest的机制
|
223
|
-
|
224
|
-
v0.0.38 重要改动,将number等参数移到perf操作,而不是类初始化中操作,继承使用上会更简单
|
225
|
-
"""
|
226
|
-
|
227
|
-
def perf(self, number=1, repeat=1, globals=None):
|
228
|
-
# 1 找到所有perf_为前缀,且callable的函数方法
|
229
|
-
funcnames = []
|
230
|
-
for k in dir(self):
|
231
|
-
if k.startswith('perf_'):
|
232
|
-
if callable(getattr(self, k)):
|
233
|
-
funcnames.append(k)
|
234
|
-
|
235
|
-
# 2 自然排序
|
236
|
-
funcnames = natural_sort(funcnames)
|
237
|
-
funcnames2 = listalign([fn[5:] for fn in funcnames], 'r')
|
238
|
-
for i, funcname in enumerate(funcnames):
|
239
|
-
perftest(funcnames2[i], getattr(self, funcname),
|
240
|
-
number=number, repeat=repeat, globals=globals)
|
241
|
-
|
242
|
-
|
243
|
-
____arrow = """
|
244
|
-
"""
|
245
|
-
|
246
|
-
|
247
|
-
class Datetime(arrow.Arrow):
|
248
|
-
r"""时间戳类
|
249
|
-
|
250
|
-
包含功能:
|
251
|
-
各种日期格式 -> 标准日期格式 -> 各种类型的输出格式
|
252
|
-
以及日期间的运算
|
253
|
-
|
254
|
-
TODO 这个库的初始化接口写的太灵活了,需要一定的限制,否则会造成使用者的模糊
|
255
|
-
"""
|
256
|
-
|
257
|
-
def __init__(self, *argv, fold=0):
|
258
|
-
r"""超高智能日期识别,能处理常见的各种输入类型来初始化一个标准时间戳值
|
259
|
-
|
260
|
-
:param fold: 暂时也没研究这个参数有什么用,就是为了兼容性先挂着
|
261
|
-
|
262
|
-
# 建议使用 Datetime.now()
|
263
|
-
>> Datetime() # 没有参数的时候,初始化为当前时间
|
264
|
-
<Datetime [2020-03-22T01:00:07.035481+00:00]>
|
265
|
-
|
266
|
-
# 正常初始化方法
|
267
|
-
>>> Datetime(2017, 2, 5, 8, 26, 58, 861782) # 标准的时间初始化方法
|
268
|
-
<Datetime [2017-02-05T08:26:58.861782+08:00]>
|
269
|
-
>>> Datetime(2017) # 可以省略月、日等值
|
270
|
-
<Datetime [2017-01-01T00:00:00+08:00]>
|
271
|
-
|
272
|
-
# 建议使用 Datetime.strptime
|
273
|
-
>>> Datetime('2019年3月6日', '%Y年%m月%d日') # 指定格式
|
274
|
-
<Datetime [2019-03-06T00:00:00+08:00]>
|
275
|
-
>>> Datetime('w200301周日', 'w%y%m%d周日') # 周日必须写全,有缺失会报ValueError
|
276
|
-
<Datetime [2020-03-01T00:00:00+08:00]>
|
277
|
-
|
278
|
-
>>> Datetime(180213)
|
279
|
-
<Datetime [2018-02-13T00:00:00+08:00]>
|
280
|
-
>>> Datetime('180213')
|
281
|
-
<Datetime [2018-02-13T00:00:00+08:00]>
|
282
|
-
|
283
|
-
>>> Datetime('2015-06-15_22-19-01_HDR.jpg')
|
284
|
-
<Datetime [2015-06-15T22:19:01+08:00]>
|
285
|
-
>>> Datetime('IMG_20150615_2219011234_HDR.jpg')
|
286
|
-
<Datetime [2015-06-15T22:19:01.001234+08:00]>
|
287
|
-
>>> Datetime('_2015.6.15_22:19:02')
|
288
|
-
<Datetime [2015-06-15T22:19:02+08:00]>
|
289
|
-
"""
|
290
|
-
dt = None
|
291
|
-
# 1 没有参数则默认当前运行时间
|
292
|
-
if not argv:
|
293
|
-
dt = datetime.datetime.now()
|
294
|
-
if not dt and isinstance(argv[0], datetime.date):
|
295
|
-
dt = datetime.datetime(argv[0].year, argv[0].month, argv[0].day)
|
296
|
-
if not dt and isinstance(argv[0], (datetime.datetime, arrow.Arrow, Datetime)):
|
297
|
-
dt = argv[0]
|
298
|
-
if not dt and isinstance(argv[0], float):
|
299
|
-
dt = datetime.datetime.fromtimestamp(argv[0])
|
300
|
-
# 2 优先尝试用标准的datetime初始化方法
|
301
|
-
if not dt:
|
302
|
-
dt = Datetime._datetime(argv)
|
303
|
-
# 3 如果上述解析不了,且argv恰好为两个参数,则判断为使用strptime初始化
|
304
|
-
if not dt and len(argv) == 2:
|
305
|
-
dt = datetime.datetime.strptime(str(argv[0]), argv[1])
|
306
|
-
# 4 判断是否我个人特用的六位日期标记
|
307
|
-
if not dt:
|
308
|
-
dt = Datetime._six_digits_date(argv[0])
|
309
|
-
# 5 如果仍然解析不了,开始使用一个智能推导算法
|
310
|
-
if not dt:
|
311
|
-
dt = Datetime._parse_time_string(argv[0])
|
312
|
-
# 6 最后任何解析方案都失败,则报错
|
313
|
-
if not dt:
|
314
|
-
print(f'无法解析输入的时间标记 argv: {argv},现重置为当前时间点')
|
315
|
-
dt = datetime.datetime.now()
|
316
|
-
|
317
|
-
super().__init__(dt.year, dt.month, dt.day,
|
318
|
-
dt.hour, dt.minute, dt.second, dt.microsecond,
|
319
|
-
'local', fold=getattr(dt, 'fold', 0))
|
320
|
-
|
321
|
-
@classmethod
|
322
|
-
def strptime(cls, data_strnig, format):
|
323
|
-
raise NotImplementedError
|
324
|
-
|
325
|
-
@staticmethod
|
326
|
-
def _datetime(argv):
|
327
|
-
args, n = list(argv), len(argv)
|
328
|
-
if n < 3: # 若没填写月、日,默认1月、1日
|
329
|
-
args = args + [1] * (3 - n)
|
330
|
-
try:
|
331
|
-
return datetime.datetime(*args)
|
332
|
-
except (ValueError, TypeError) as e:
|
333
|
-
return None
|
334
|
-
|
335
|
-
@staticmethod
|
336
|
-
def _six_digits_date(s):
|
337
|
-
"""主要是我个人常用的日期标注格式
|
338
|
-
"""
|
339
|
-
s, dt = str(s), None
|
340
|
-
if re.match(r'\d{6}$', s):
|
341
|
-
year = int(s[:2])
|
342
|
-
year = 2000 + year if year < 50 else 1900 + year # 小于50默认是20xx年,否则认为是19xx年
|
343
|
-
dt = Datetime._datetime([year, int(s[2:4]), int(s[4:])])
|
344
|
-
return dt
|
345
|
-
|
346
|
-
@staticmethod
|
347
|
-
def _parse_time_string(s):
|
348
|
-
r"""只对2000~2099年的时间点有效
|
349
|
-
"""
|
350
|
-
data, break_flag = [], False
|
351
|
-
|
352
|
-
def parse(pattern, left=None, right=None):
|
353
|
-
"""通用底层解析器"""
|
354
|
-
nonlocal break_flag, s
|
355
|
-
if break_flag: return
|
356
|
-
|
357
|
-
m = re.search(pattern, s)
|
358
|
-
if m:
|
359
|
-
d = int(m.group())
|
360
|
-
if left and d < left:
|
361
|
-
break_flag = True
|
362
|
-
elif right and d > right:
|
363
|
-
break_flag = True
|
364
|
-
else:
|
365
|
-
data.append(d)
|
366
|
-
s = s[m.end():]
|
367
|
-
else:
|
368
|
-
break_flag = True
|
369
|
-
|
370
|
-
parse(r'20\d{2}')
|
371
|
-
parse(r'\d\d?', 1, 12) # 有连续两个数组就获得两个,否则获得一个也行
|
372
|
-
parse(r'\d\d?', 1, 31) # 这样其实不严谨,有的月份不到31天,不过反正_datetime会返回None代表处理失败的
|
373
|
-
parse(r'\d\d?', 0, 23)
|
374
|
-
parse(r'\d\d?', 0, 59)
|
375
|
-
parse(r'\d\d?', 0, 59)
|
376
|
-
parse(r'\d{1,6}') # microsecond
|
377
|
-
|
378
|
-
return Datetime._datetime(data)
|
379
|
-
|
380
|
-
def replace(self, **kwargs):
|
381
|
-
"""
|
382
|
-
'weekday',1~7分别代表周一到周日
|
383
|
-
|
384
|
-
>>> Datetime(180826).replace(weekday=1).strftime('%y%m%d周%k')
|
385
|
-
'180820周一'
|
386
|
-
>>> Datetime(180826).replace(weekday=3).strftime('%y%m%d周%k')
|
387
|
-
'180822周三'
|
388
|
-
"""
|
389
|
-
a = self
|
390
|
-
if 'weekday' in kwargs:
|
391
|
-
if set(kwargs.keys()) & {'year', 'month', 'day'}:
|
392
|
-
raise ValueError('weekday参数不能混合年月日的修改使用')
|
393
|
-
a = a - a.isoweekday() + kwargs['weekday'] # 先减去当前星期几,再加上1~7的一个目标星期
|
394
|
-
del kwargs['weekday']
|
395
|
-
if kwargs:
|
396
|
-
a = a.replace(**kwargs)
|
397
|
-
return Datetime(a)
|
398
|
-
|
399
|
-
def __add__(self, other):
|
400
|
-
"""加减数值时,单位按天处理"""
|
401
|
-
if isinstance(other, (int, float)):
|
402
|
-
other = datetime.timedelta(other)
|
403
|
-
return Datetime(super().__add__(other))
|
404
|
-
|
405
|
-
def __sub__(self, other):
|
406
|
-
if isinstance(other, (int, float)):
|
407
|
-
other = datetime.timedelta(other)
|
408
|
-
return Datetime(super().__sub__(other))
|
409
|
-
|
410
|
-
def shift(self, **kwargs):
|
411
|
-
"""shift 有点像游标卡尺,可以左右两边进行加减移位操作,加减的对象可以是年月日时分秒和星期。
|
412
|
-
|
413
|
-
>>> a = Datetime(2018, 8, 24)
|
414
|
-
>>> a.shift(months=-1)
|
415
|
-
<Datetime [2018-07-24T00:00:00+08:00]>
|
416
|
-
>>> a.shift(months=-1).format("YYYYMM")
|
417
|
-
'201807'
|
418
|
-
>>> a.shift(weeks=1)
|
419
|
-
<Datetime [2018-08-31T00:00:00+08:00]>
|
420
|
-
"""
|
421
|
-
return Datetime(super().shift(**kwargs))
|
422
|
-
|
423
|
-
def to(self, tz):
|
424
|
-
"""to 可以将一个本地时区转换成其它任意时区,例如:
|
425
|
-
|
426
|
-
>>> a = Datetime(2020, 6, 1, 17)
|
427
|
-
>>> a.to("utc")
|
428
|
-
<Datetime [2020-06-01T09:00:00+08:00]>
|
429
|
-
>>> a.to("utc").to("local")
|
430
|
-
<Datetime [2020-06-01T09:00:00+08:00]>
|
431
|
-
>>> a.to("America/New_York")
|
432
|
-
<Datetime [2020-06-01T05:00:00+08:00]>
|
433
|
-
"""
|
434
|
-
return Datetime(super().to(tz))
|
435
|
-
|
436
|
-
def humanize(self, other=None, locale="zh", only_distance=False, granularity="auto"):
|
437
|
-
r""" humanize 方法是相对于当前时刻表示为“多久以前”的一种可读行字符串形式,
|
438
|
-
默认是英文格式,指定 locale 可显示相应的语言格式。
|
439
|
-
|
440
|
-
>>> a = Datetime().shift(hours=-6)
|
441
|
-
>>> a.humanize()
|
442
|
-
'6小时前'
|
443
|
-
>>> a.humanize(locale='en')
|
444
|
-
'6 hours ago'
|
445
|
-
|
446
|
-
这是从 https://mp.weixin.qq.com/s/DqD_PmrspMeytloV_o54IA 摘录的Arrow的文档
|
447
|
-
并不是该Datetime类本身的文档,但意思差不多,可以参考
|
448
|
-
"""
|
449
|
-
return super().humanize(other, locale, only_distance, granularity)
|
450
|
-
|
451
|
-
def strftime(self, fmt='%Y/%m/%d'):
|
452
|
-
r"""做了简单格式拓展
|
453
|
-
|
454
|
-
官方支持的符号: https://docs.python.org/3/library/datetime.html#strftime-strptime-behavior
|
455
|
-
|
456
|
-
我自己扩展的功能:
|
457
|
-
%k,周几:一、二、三、四、五、六、日
|
458
|
-
|
459
|
-
>>> dt = Datetime(2020, 2, 28, 9, 10, 52)
|
460
|
-
>>> dt.strftime('%y%m%d')
|
461
|
-
'200228'
|
462
|
-
>>> dt.strftime('%Y/%m/%d')
|
463
|
-
'2020/02/28'
|
464
|
-
>>> dt.strftime('%y%m%d周%k') # 我自己最常用的格式
|
465
|
-
'200228周五'
|
466
|
-
"""
|
467
|
-
# 先用占位符替代中文,和我扩展的%k等标记
|
468
|
-
fmt1 = re.sub(r'([\u4e00-\u9fa5,。;?()【】、①-⑨]|%k)', r'{placeholder}', fmt)
|
469
|
-
tag = super().strftime(fmt1)
|
470
|
-
if fmt1 != fmt:
|
471
|
-
texts = re.findall(r'([\u4e00-\u9fa5,。;?()【】、①-⑨]|%k)', fmt)
|
472
|
-
for i in range(len(texts)):
|
473
|
-
tag = tag.replace('{placeholder}', texts[i], 1)
|
474
|
-
tag = tag.replace('%k', '日一二三四五六'[self.isoweekday() % 7])
|
475
|
-
return tag
|
476
|
-
|
477
|
-
|
478
|
-
if __name__ == '__main__':
|
479
|
-
# demo:每个脚本开头结尾都可以这样写来统计程序用时
|
480
|
-
TicToc.process_time(f'{__file__} 启动准备共用时')
|
481
|
-
# D:/slns/pyxllib/pyxllib/basic/_2_timelib.py 启动准备共用时 0.031 秒
|
482
|
-
|
483
|
-
tictoc = TicToc(__file__)
|
484
|
-
|
485
|
-
time.sleep(2)
|
486
|
-
|
487
|
-
tictoc.toc()
|
488
|
-
# D:/slns/pyxllib/pyxllib/basic/_2_timelib.py 用时 2.000 秒.
|