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.
Files changed (186) hide show
  1. pyxllib/__init__.py +9 -2
  2. pyxllib/algo/__init__.py +8 -0
  3. pyxllib/algo/disjoint.py +54 -0
  4. pyxllib/algo/geo.py +541 -0
  5. pyxllib/{util/mathlib.py → algo/intervals.py} +172 -36
  6. pyxllib/algo/matcher.py +389 -0
  7. pyxllib/algo/newbie.py +166 -0
  8. pyxllib/algo/pupil.py +629 -0
  9. pyxllib/algo/shapelylib.py +67 -0
  10. pyxllib/algo/specialist.py +241 -0
  11. pyxllib/algo/stat.py +494 -0
  12. pyxllib/algo/treelib.py +149 -0
  13. pyxllib/algo/unitlib.py +66 -0
  14. pyxllib/autogui/__init__.py +5 -0
  15. pyxllib/autogui/activewin.py +246 -0
  16. pyxllib/autogui/all.py +9 -0
  17. pyxllib/autogui/autogui.py +852 -0
  18. pyxllib/autogui/uiautolib.py +362 -0
  19. pyxllib/autogui/virtualkey.py +102 -0
  20. pyxllib/autogui/wechat.py +827 -0
  21. pyxllib/autogui/wechat_msg.py +421 -0
  22. pyxllib/autogui/wxautolib.py +84 -0
  23. pyxllib/cv/__init__.py +1 -11
  24. pyxllib/cv/expert.py +267 -0
  25. pyxllib/cv/{imlib.py → imfile.py} +18 -83
  26. pyxllib/cv/imhash.py +39 -0
  27. pyxllib/cv/pupil.py +9 -0
  28. pyxllib/cv/rgbfmt.py +1525 -0
  29. pyxllib/cv/slidercaptcha.py +137 -0
  30. pyxllib/cv/trackbartools.py +163 -49
  31. pyxllib/cv/xlcvlib.py +1040 -0
  32. pyxllib/cv/xlpillib.py +423 -0
  33. pyxllib/data/__init__.py +0 -0
  34. pyxllib/data/echarts.py +240 -0
  35. pyxllib/data/jsonlib.py +89 -0
  36. pyxllib/{util/oss2_.py → data/oss.py} +11 -9
  37. pyxllib/data/pglib.py +1127 -0
  38. pyxllib/data/sqlite.py +568 -0
  39. pyxllib/{util → data}/sqllib.py +13 -31
  40. pyxllib/ext/JLineViewer.py +505 -0
  41. pyxllib/ext/__init__.py +6 -0
  42. pyxllib/{util → ext}/demolib.py +119 -35
  43. pyxllib/ext/drissionlib.py +277 -0
  44. pyxllib/ext/kq5034lib.py +12 -0
  45. pyxllib/{util/main.py → ext/old.py} +122 -284
  46. pyxllib/ext/qt.py +449 -0
  47. pyxllib/ext/robustprocfile.py +497 -0
  48. pyxllib/ext/seleniumlib.py +76 -0
  49. pyxllib/{util/tklib.py → ext/tk.py} +10 -11
  50. pyxllib/ext/unixlib.py +827 -0
  51. pyxllib/ext/utools.py +351 -0
  52. pyxllib/{util/webhooklib.py → ext/webhook.py} +45 -17
  53. pyxllib/ext/win32lib.py +40 -0
  54. pyxllib/ext/wjxlib.py +88 -0
  55. pyxllib/ext/wpsapi.py +124 -0
  56. pyxllib/ext/xlwork.py +9 -0
  57. pyxllib/ext/yuquelib.py +1105 -0
  58. pyxllib/file/__init__.py +17 -0
  59. pyxllib/file/docxlib.py +761 -0
  60. pyxllib/{util → file}/gitlib.py +40 -27
  61. pyxllib/file/libreoffice.py +165 -0
  62. pyxllib/file/movielib.py +148 -0
  63. pyxllib/file/newbie.py +10 -0
  64. pyxllib/file/onenotelib.py +1469 -0
  65. pyxllib/file/packlib/__init__.py +330 -0
  66. pyxllib/{util → file/packlib}/zipfile.py +598 -195
  67. pyxllib/file/pdflib.py +426 -0
  68. pyxllib/file/pupil.py +185 -0
  69. pyxllib/file/specialist/__init__.py +685 -0
  70. pyxllib/{basic/_5_dirlib.py → file/specialist/dirlib.py} +364 -93
  71. pyxllib/file/specialist/download.py +193 -0
  72. pyxllib/file/specialist/filelib.py +2829 -0
  73. pyxllib/file/xlsxlib.py +3131 -0
  74. pyxllib/file/xlsyncfile.py +341 -0
  75. pyxllib/prog/__init__.py +5 -0
  76. pyxllib/prog/cachetools.py +64 -0
  77. pyxllib/prog/deprecatedlib.py +233 -0
  78. pyxllib/prog/filelock.py +42 -0
  79. pyxllib/prog/ipyexec.py +253 -0
  80. pyxllib/prog/multiprogs.py +940 -0
  81. pyxllib/prog/newbie.py +451 -0
  82. pyxllib/prog/pupil.py +1197 -0
  83. pyxllib/{sitepackages.py → prog/sitepackages.py} +5 -3
  84. pyxllib/prog/specialist/__init__.py +391 -0
  85. pyxllib/prog/specialist/bc.py +203 -0
  86. pyxllib/prog/specialist/browser.py +497 -0
  87. pyxllib/prog/specialist/common.py +347 -0
  88. pyxllib/prog/specialist/datetime.py +199 -0
  89. pyxllib/prog/specialist/tictoc.py +240 -0
  90. pyxllib/prog/specialist/xllog.py +180 -0
  91. pyxllib/prog/xlosenv.py +108 -0
  92. pyxllib/stdlib/__init__.py +17 -0
  93. pyxllib/{util → stdlib}/tablepyxl/__init__.py +1 -3
  94. pyxllib/{util → stdlib}/tablepyxl/style.py +1 -1
  95. pyxllib/{util → stdlib}/tablepyxl/tablepyxl.py +2 -4
  96. pyxllib/text/__init__.py +8 -0
  97. pyxllib/text/ahocorasick.py +39 -0
  98. pyxllib/text/airscript.js +744 -0
  99. pyxllib/text/charclasslib.py +121 -0
  100. pyxllib/text/jiebalib.py +267 -0
  101. pyxllib/text/jinjalib.py +32 -0
  102. pyxllib/text/jsa_ai_prompt.md +271 -0
  103. pyxllib/text/jscode.py +922 -0
  104. pyxllib/text/latex/__init__.py +158 -0
  105. pyxllib/text/levenshtein.py +303 -0
  106. pyxllib/text/nestenv.py +1215 -0
  107. pyxllib/text/newbie.py +300 -0
  108. pyxllib/text/pupil/__init__.py +8 -0
  109. pyxllib/text/pupil/common.py +1121 -0
  110. pyxllib/text/pupil/xlalign.py +326 -0
  111. pyxllib/text/pycode.py +47 -0
  112. pyxllib/text/specialist/__init__.py +8 -0
  113. pyxllib/text/specialist/common.py +112 -0
  114. pyxllib/text/specialist/ptag.py +186 -0
  115. pyxllib/text/spellchecker.py +172 -0
  116. pyxllib/text/templates/echart_base.html +11 -0
  117. pyxllib/text/templates/highlight_code.html +17 -0
  118. pyxllib/text/templates/latex_editor.html +103 -0
  119. pyxllib/text/vbacode.py +17 -0
  120. pyxllib/text/xmllib.py +747 -0
  121. pyxllib/xl.py +39 -0
  122. pyxllib/xlcv.py +17 -0
  123. pyxllib-0.3.197.dist-info/METADATA +48 -0
  124. pyxllib-0.3.197.dist-info/RECORD +126 -0
  125. {pyxllib-0.0.43.dist-info → pyxllib-0.3.197.dist-info}/WHEEL +4 -5
  126. pyxllib/basic/_1_strlib.py +0 -945
  127. pyxllib/basic/_2_timelib.py +0 -488
  128. pyxllib/basic/_3_pathlib.py +0 -916
  129. pyxllib/basic/_4_loglib.py +0 -419
  130. pyxllib/basic/__init__.py +0 -54
  131. pyxllib/basic/arrow_.py +0 -250
  132. pyxllib/basic/chardet_.py +0 -66
  133. pyxllib/basic/dirlib.py +0 -529
  134. pyxllib/basic/dprint.py +0 -202
  135. pyxllib/basic/extension.py +0 -12
  136. pyxllib/basic/judge.py +0 -31
  137. pyxllib/basic/log.py +0 -204
  138. pyxllib/basic/pathlib_.py +0 -705
  139. pyxllib/basic/pytictoc.py +0 -102
  140. pyxllib/basic/qiniu_.py +0 -61
  141. pyxllib/basic/strlib.py +0 -761
  142. pyxllib/basic/timer.py +0 -132
  143. pyxllib/cv/cv.py +0 -834
  144. pyxllib/cv/cvlib/_1_geo.py +0 -543
  145. pyxllib/cv/cvlib/_2_cvprcs.py +0 -309
  146. pyxllib/cv/cvlib/_2_imgproc.py +0 -594
  147. pyxllib/cv/cvlib/_3_pilprcs.py +0 -80
  148. pyxllib/cv/cvlib/_4_cvimg.py +0 -211
  149. pyxllib/cv/cvlib/__init__.py +0 -10
  150. pyxllib/cv/debugtools.py +0 -82
  151. pyxllib/cv/fitz_.py +0 -300
  152. pyxllib/cv/installer.py +0 -42
  153. pyxllib/debug/_0_installer.py +0 -38
  154. pyxllib/debug/_1_typelib.py +0 -277
  155. pyxllib/debug/_2_chrome.py +0 -198
  156. pyxllib/debug/_3_showdir.py +0 -161
  157. pyxllib/debug/_4_bcompare.py +0 -140
  158. pyxllib/debug/__init__.py +0 -49
  159. pyxllib/debug/bcompare.py +0 -132
  160. pyxllib/debug/chrome.py +0 -198
  161. pyxllib/debug/installer.py +0 -38
  162. pyxllib/debug/showdir.py +0 -158
  163. pyxllib/debug/typelib.py +0 -278
  164. pyxllib/image/__init__.py +0 -12
  165. pyxllib/torch/__init__.py +0 -20
  166. pyxllib/torch/modellib.py +0 -37
  167. pyxllib/torch/trainlib.py +0 -344
  168. pyxllib/util/__init__.py +0 -20
  169. pyxllib/util/aip_.py +0 -141
  170. pyxllib/util/casiadb.py +0 -59
  171. pyxllib/util/excellib.py +0 -495
  172. pyxllib/util/filelib.py +0 -612
  173. pyxllib/util/jsondata.py +0 -27
  174. pyxllib/util/jsondata2.py +0 -92
  175. pyxllib/util/labelmelib.py +0 -139
  176. pyxllib/util/onepy/__init__.py +0 -29
  177. pyxllib/util/onepy/onepy.py +0 -574
  178. pyxllib/util/onepy/onmanager.py +0 -170
  179. pyxllib/util/pyautogui_.py +0 -219
  180. pyxllib/util/textlib.py +0 -1305
  181. pyxllib/util/unorder.py +0 -22
  182. pyxllib/util/xmllib.py +0 -639
  183. pyxllib-0.0.43.dist-info/METADATA +0 -39
  184. pyxllib-0.0.43.dist-info/RECORD +0 -80
  185. pyxllib-0.0.43.dist-info/top_level.txt +0 -1
  186. {pyxllib-0.0.43.dist-info → pyxllib-0.3.197.dist-info/licenses}/LICENSE +0 -0
@@ -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 秒.