upplib 3.3.8__tar.gz → 3.3.9__tar.gz
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.
- {upplib-3.3.8 → upplib-3.3.9}/PKG-INFO +1 -1
- {upplib-3.3.8 → upplib-3.3.9}/upplib/__init__.py +2 -1
- {upplib-3.3.8 → upplib-3.3.9}/upplib/config_data.py +1 -1
- upplib-3.3.9/upplib/datetime_function.py +256 -0
- {upplib-3.3.8 → upplib-3.3.9}/upplib/file_to_text.py +1 -1
- {upplib-3.3.8 → upplib-3.3.9}/upplib/index.py +0 -252
- {upplib-3.3.8 → upplib-3.3.9}/upplib/text_to_file.py +1 -1
- {upplib-3.3.8 → upplib-3.3.9}/upplib.egg-info/PKG-INFO +1 -1
- {upplib-3.3.8 → upplib-3.3.9}/upplib.egg-info/SOURCES.txt +2 -1
- {upplib-3.3.8 → upplib-3.3.9}/LICENSE +0 -0
- {upplib-3.3.8 → upplib-3.3.9}/README.md +0 -0
- {upplib-3.3.8 → upplib-3.3.9}/pyproject.toml +0 -0
- {upplib-3.3.8 → upplib-3.3.9}/setup.cfg +0 -0
- {upplib-3.3.8 → upplib-3.3.9}/setup.py +0 -0
- {upplib-3.3.8 → upplib-3.3.9}/upplib/chart.py +0 -0
- {upplib-3.3.8 → upplib-3.3.9}/upplib/chart_html.py +0 -0
- {upplib-3.3.8 → upplib-3.3.9}/upplib/clean_up_msg.py +0 -0
- {upplib-3.3.8 → upplib-3.3.9}/upplib/common_package.py +0 -0
- {upplib-3.3.8 → upplib-3.3.9}/upplib/db.py +0 -0
- /upplib-3.3.8/upplib/file.py → /upplib-3.3.9/upplib/file_function.py +0 -0
- {upplib-3.3.8 → upplib-3.3.9}/upplib/format_data.py +0 -0
- {upplib-3.3.8 → upplib-3.3.9}/upplib/http_util.py +0 -0
- {upplib-3.3.8 → upplib-3.3.9}/upplib/mail.py +0 -0
- {upplib-3.3.8 → upplib-3.3.9}/upplib/mail_html.py +0 -0
- {upplib-3.3.8 → upplib-3.3.9}/upplib/markdown.py +0 -0
- {upplib-3.3.8 → upplib-3.3.9}/upplib/multi_thread.py +0 -0
- {upplib-3.3.8 → upplib-3.3.9}/upplib/query_log.py +0 -0
- {upplib-3.3.8 → upplib-3.3.9}/upplib/redis_tool.py +0 -0
- {upplib-3.3.8 → upplib-3.3.9}/upplib/util.py +0 -0
- {upplib-3.3.8 → upplib-3.3.9}/upplib.egg-info/dependency_links.txt +0 -0
- {upplib-3.3.8 → upplib-3.3.9}/upplib.egg-info/requires.txt +0 -0
- {upplib-3.3.8 → upplib-3.3.9}/upplib.egg-info/top_level.txt +0 -0
|
@@ -3,11 +3,12 @@ from upplib.common_package import *
|
|
|
3
3
|
|
|
4
4
|
# 引入自定义的全部的包
|
|
5
5
|
from upplib.index import *
|
|
6
|
+
from upplib.datetime_function import *
|
|
6
7
|
# 引入通用的工具包
|
|
7
8
|
from upplib.util import *
|
|
8
9
|
|
|
9
10
|
# 有关文件操作类的包
|
|
10
|
-
from upplib.
|
|
11
|
+
from upplib.file_function import *
|
|
11
12
|
from upplib.file_to_text import *
|
|
12
13
|
from upplib.text_to_file import *
|
|
13
14
|
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
from upplib import *
|
|
2
|
+
from datetime import datetime, timezone, timedelta
|
|
3
|
+
from typing import Any, Optional, Union
|
|
4
|
+
from upplib.common_package import *
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def get_tz(tz_info: Union[str, timezone]) -> timezone:
|
|
8
|
+
"""将时区信息转换为timezone对象"""
|
|
9
|
+
if isinstance(tz_info, timezone):
|
|
10
|
+
return tz_info
|
|
11
|
+
if not isinstance(tz_info, str):
|
|
12
|
+
raise ValueError(f"无效的时区格式: {tz_info}")
|
|
13
|
+
tz_str = tz_info.upper()
|
|
14
|
+
if tz_str == "UTC":
|
|
15
|
+
return timezone.utc
|
|
16
|
+
# 处理纯偏移格式,如+07:00、-05:30
|
|
17
|
+
offset_match = re.match(r"^([+-])(\d{1,2}):(\d{2})$", tz_str)
|
|
18
|
+
if offset_match:
|
|
19
|
+
sign = offset_match.group(1)
|
|
20
|
+
hours = int(offset_match.group(2))
|
|
21
|
+
minutes = int(offset_match.group(3))
|
|
22
|
+
# 计算总偏移小时数
|
|
23
|
+
total_hours = hours + minutes / 60
|
|
24
|
+
if sign == "-":
|
|
25
|
+
total_hours = -total_hours
|
|
26
|
+
return timezone(timedelta(hours=total_hours))
|
|
27
|
+
# 处理GMT格式,如GMT+08:00或GMT-5
|
|
28
|
+
gmt_match = re.match(r"GMT([+-]\d{1,2})(:\d{2})?$", tz_str)
|
|
29
|
+
if gmt_match:
|
|
30
|
+
hours = int(gmt_match.group(1))
|
|
31
|
+
return timezone(timedelta(hours=hours))
|
|
32
|
+
# 处理UTC格式,如UTC+8或UTC-05:00
|
|
33
|
+
utc_match = re.match(r"UTC([+-]\d{1,2})(:\d{2})?$", tz_str)
|
|
34
|
+
if utc_match:
|
|
35
|
+
hours = int(utc_match.group(1))
|
|
36
|
+
return timezone(timedelta(hours=hours))
|
|
37
|
+
raise ValueError(f"不支持的时区格式: {tz_info}")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def to_datetime(
|
|
41
|
+
s: Any = None,
|
|
42
|
+
pattern: str = None,
|
|
43
|
+
r_str: bool = False,
|
|
44
|
+
error_is_none: bool = False,
|
|
45
|
+
tz: Optional[Union[str, timezone]] = None,
|
|
46
|
+
default_tz: Union[str, timezone] = None
|
|
47
|
+
) -> Union[datetime, str, None]:
|
|
48
|
+
"""
|
|
49
|
+
将字符串或时间戳转换为 datetime 对象,支持时区处理。
|
|
50
|
+
error_is_none : 当发生错误的时候,是否返回 None
|
|
51
|
+
"""
|
|
52
|
+
# 默认时区为 +08:00
|
|
53
|
+
default_tz = default_tz or '+08:00'
|
|
54
|
+
|
|
55
|
+
use_default_time = False
|
|
56
|
+
if s is None or s == '':
|
|
57
|
+
dt = datetime.now(get_tz(default_tz))
|
|
58
|
+
else:
|
|
59
|
+
s = str(s).strip()
|
|
60
|
+
dt = None
|
|
61
|
+
|
|
62
|
+
# 1. 尝试解析时间戳
|
|
63
|
+
if re.match(r"^\d{1,19}$", s):
|
|
64
|
+
timestamp = int(s)
|
|
65
|
+
if len(s) > 10: # 毫秒级时间戳
|
|
66
|
+
timestamp = timestamp // 1000
|
|
67
|
+
# 先转为无时区的 datetime
|
|
68
|
+
dt = datetime.fromtimestamp(timestamp)
|
|
69
|
+
dt = dt.replace(tzinfo=get_tz(default_tz))
|
|
70
|
+
|
|
71
|
+
# 2. 尝试解析 ISO 8601 格式
|
|
72
|
+
if dt is None:
|
|
73
|
+
try:
|
|
74
|
+
dt = datetime.fromisoformat(s)
|
|
75
|
+
except ValueError:
|
|
76
|
+
pass
|
|
77
|
+
|
|
78
|
+
# 3. 尝试解析带GMT时区的格式,如'2025/09/16 17:32:17.896 GMT+08:00'
|
|
79
|
+
if dt is None:
|
|
80
|
+
gmt_pattern = r"^(\d{4})[/-](\d{2})[/-](\d{2}) (\d{2}):(\d{2}):(\d{2})(\.\d+)? (GMT[+-]\d{1,2}(:\d{2})?)$"
|
|
81
|
+
match = re.match(gmt_pattern, s)
|
|
82
|
+
if match:
|
|
83
|
+
try:
|
|
84
|
+
# 提取日期时间部分
|
|
85
|
+
year, month, day = map(int, match.group(1, 2, 3))
|
|
86
|
+
hour, minute, second = map(int, match.group(4, 5, 6))
|
|
87
|
+
microsecond = 0
|
|
88
|
+
if match.group(7):
|
|
89
|
+
# 处理毫秒/微秒部分
|
|
90
|
+
microsecond = int(float(match.group(7)) * 1e6)
|
|
91
|
+
|
|
92
|
+
# 创建datetime对象
|
|
93
|
+
dt = datetime(year, month, day, hour, minute, second, microsecond)
|
|
94
|
+
|
|
95
|
+
# 应用时区
|
|
96
|
+
tz_info = get_tz(match.group(8))
|
|
97
|
+
dt = dt.replace(tzinfo=tz_info)
|
|
98
|
+
except ValueError:
|
|
99
|
+
pass
|
|
100
|
+
|
|
101
|
+
# 4. 使用指定的pattern解析
|
|
102
|
+
if dt is None and pattern is not None:
|
|
103
|
+
try:
|
|
104
|
+
# 移除可能的毫秒部分
|
|
105
|
+
s_without_ms = s.split('.')[0]
|
|
106
|
+
dt = datetime.strptime(s_without_ms, pattern)
|
|
107
|
+
except ValueError:
|
|
108
|
+
pass
|
|
109
|
+
|
|
110
|
+
# 5. 尝试解析YYYY-MM-DD HH:MM:SS或YYYY/MM/DD HH:MM:SS格式
|
|
111
|
+
if dt is None:
|
|
112
|
+
# 尝试处理不带时区的格式
|
|
113
|
+
formats = ["%Y-%m-%d %H:%M:%S", "%Y/%m/%d %H:%M:%S"]
|
|
114
|
+
for fmt in formats:
|
|
115
|
+
try:
|
|
116
|
+
# 移除可能的毫秒和时区部分
|
|
117
|
+
s_clean = re.sub(r"(\.\d+)|[TZ]|GMT.*$", " ", s).strip()
|
|
118
|
+
dt = datetime.strptime(s_clean, fmt)
|
|
119
|
+
break
|
|
120
|
+
except ValueError:
|
|
121
|
+
continue
|
|
122
|
+
|
|
123
|
+
if dt is None:
|
|
124
|
+
use_default_time = True
|
|
125
|
+
dt = datetime.now()
|
|
126
|
+
|
|
127
|
+
# 确保无时区时附加默认时区
|
|
128
|
+
if dt.tzinfo is None:
|
|
129
|
+
dt = dt.replace(tzinfo=get_tz(default_tz))
|
|
130
|
+
|
|
131
|
+
# 转换为目标时区
|
|
132
|
+
if tz is not None:
|
|
133
|
+
dt = dt.astimezone(get_tz(tz))
|
|
134
|
+
|
|
135
|
+
if error_is_none and use_default_time:
|
|
136
|
+
return None
|
|
137
|
+
|
|
138
|
+
return dt.isoformat() if r_str else dt
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
# 将字符串 s 转化成 datetime, 然后再次转化成 str
|
|
142
|
+
def to_datetime_str(s: Any = None,
|
|
143
|
+
pattern: str = None,
|
|
144
|
+
pattern_str: str = None,
|
|
145
|
+
tz: Optional[Union[str, timezone]] = None,
|
|
146
|
+
default_tz: Union[str, timezone] = None) -> datetime | str:
|
|
147
|
+
"""
|
|
148
|
+
将 s 先转成 datetime, 然后再转成字符串
|
|
149
|
+
|
|
150
|
+
:param s: 输入值(可以是字符串或其他类型)
|
|
151
|
+
"""
|
|
152
|
+
r_s = to_datetime(s, pattern=pattern, tz=tz, r_str=False, default_tz=default_tz)
|
|
153
|
+
if pattern_str is None:
|
|
154
|
+
iso_str = r_s.isoformat()
|
|
155
|
+
if '.' not in iso_str:
|
|
156
|
+
# '2025-10-09T10:52:41+08:00'
|
|
157
|
+
return iso_str
|
|
158
|
+
parts = iso_str.split('.')
|
|
159
|
+
time_zone_part = parts[1]
|
|
160
|
+
time_zone_str = tz
|
|
161
|
+
millisecond_part = time_zone_part[:3]
|
|
162
|
+
for a in ['+', '-']:
|
|
163
|
+
if a in time_zone_part:
|
|
164
|
+
time_zone_str = a + time_zone_part.split(a)[-1]
|
|
165
|
+
return parts[0] + '.' + millisecond_part + time_zone_str
|
|
166
|
+
else:
|
|
167
|
+
return r_s.strftime(pattern_str)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def to_datetime_format(s: Any = None,
|
|
171
|
+
pattern_str: str = "%Y-%m-%d %H:%M:%S") -> datetime | str:
|
|
172
|
+
return to_datetime_str(s, pattern=None, pattern_str=pattern_str, tz=None)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def to_datetime_format__6(s: Any = None,
|
|
176
|
+
pattern_str: str = "%Y-%m-%d %H:%M:%S") -> datetime | str:
|
|
177
|
+
return to_datetime_str(s, pattern=None, pattern_str=pattern_str, tz='-06:00')
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def to_datetime_format_7(s: Any = None,
|
|
181
|
+
pattern_str: str = "%Y-%m-%d %H:%M:%S") -> datetime | str:
|
|
182
|
+
return to_datetime_str(s, pattern=None, pattern_str=pattern_str, tz='+07:00')
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def to_datetime_format_8(s: Any = None,
|
|
186
|
+
pattern_str: str = "%Y-%m-%d %H:%M:%S") -> datetime | str:
|
|
187
|
+
return to_datetime_str(s, pattern=None, pattern_str=pattern_str, tz='+08:00')
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
# 时间加减
|
|
191
|
+
def to_datetime_add(s: Any = None,
|
|
192
|
+
days: int = 0,
|
|
193
|
+
seconds: int = 0,
|
|
194
|
+
microseconds: int = 0,
|
|
195
|
+
milliseconds: int = 0,
|
|
196
|
+
minutes: int = 0,
|
|
197
|
+
hours: int = 0,
|
|
198
|
+
weeks: int = 0) -> datetime:
|
|
199
|
+
return to_datetime(s) + timedelta(days=days, seconds=seconds, microseconds=microseconds,
|
|
200
|
+
milliseconds=milliseconds, minutes=minutes, hours=hours,
|
|
201
|
+
weeks=weeks)
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
# 将字符串 s 转化成 date 例如: 2021-02-03
|
|
205
|
+
def to_date(s: Any = None) -> str:
|
|
206
|
+
return str(to_datetime(s))[0:10]
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
# 将字符串 s 转化成 date 例如: 20210203
|
|
210
|
+
def to_date_number(s: Any = None) -> str:
|
|
211
|
+
return str(to_datetime(s))[0:10].replace('-', '')
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def get_timestamp(s: Any = None) -> int:
|
|
215
|
+
"""获取 Unix 秒级时间戳"""
|
|
216
|
+
return int(to_datetime(s).timestamp())
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def get_datetime_number_str(s: Any = None,
|
|
220
|
+
length: int = None,
|
|
221
|
+
remove_dz: bool = True,
|
|
222
|
+
) -> str:
|
|
223
|
+
"""获取 datetime , 然后转成字符串, 然后, 只保留数字
|
|
224
|
+
Args:
|
|
225
|
+
s: 输入值,可以是任何类型,如果是None则使用当前时间
|
|
226
|
+
length: 可选参数,指定返回字符串的长度
|
|
227
|
+
remove_dz: 是否去掉时区
|
|
228
|
+
Returns:
|
|
229
|
+
str: 只包含数字的字符串
|
|
230
|
+
"""
|
|
231
|
+
s1 = to_datetime(s)
|
|
232
|
+
digits_only = re.sub(r'\D', '', str(s1))
|
|
233
|
+
# 如果指定了长度,取最后length位
|
|
234
|
+
if length is not None and length > 0:
|
|
235
|
+
return digits_only[-length:] if len(digits_only) > length else digits_only
|
|
236
|
+
if len(digits_only) > 4 and remove_dz:
|
|
237
|
+
digits_only = digits_only[:-4]
|
|
238
|
+
return digits_only
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def get_timestamp_ms(s: Any = None) -> int:
|
|
242
|
+
"""获取 Unix 毫秒级时间戳"""
|
|
243
|
+
return int(to_datetime(s).timestamp() * 1000)
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
# 时间加减
|
|
247
|
+
def to_date_add(s: Any = None,
|
|
248
|
+
days: int = 0,
|
|
249
|
+
seconds: int = 0,
|
|
250
|
+
microseconds: int = 0,
|
|
251
|
+
milliseconds: int = 0,
|
|
252
|
+
minutes: int = 0,
|
|
253
|
+
hours: int = 0,
|
|
254
|
+
weeks: int = 0) -> str:
|
|
255
|
+
return str(to_datetime_add(s=s, days=days, seconds=seconds, microseconds=microseconds,
|
|
256
|
+
milliseconds=milliseconds, minutes=minutes, hours=hours, weeks=weeks))[0:10]
|
|
@@ -4,7 +4,6 @@ from typing import Any, Optional, Union
|
|
|
4
4
|
from upplib.common_package import *
|
|
5
5
|
from collections import defaultdict
|
|
6
6
|
|
|
7
|
-
|
|
8
7
|
# 创建一个线程本地存储对象
|
|
9
8
|
__THREAD_LOCAL_INDEX_DATA = threading.local()
|
|
10
9
|
|
|
@@ -254,257 +253,6 @@ def to_float(s: Any = None,
|
|
|
254
253
|
return value
|
|
255
254
|
|
|
256
255
|
|
|
257
|
-
def to_datetime(
|
|
258
|
-
s: Any = None,
|
|
259
|
-
pattern: str = None,
|
|
260
|
-
r_str: bool = False,
|
|
261
|
-
error_is_none: bool = False,
|
|
262
|
-
tz: Optional[Union[str, timezone]] = None,
|
|
263
|
-
default_tz: Union[str, timezone] = None
|
|
264
|
-
) -> Union[datetime, str, None]:
|
|
265
|
-
"""
|
|
266
|
-
将字符串或时间戳转换为 datetime 对象,支持时区处理。
|
|
267
|
-
error_is_none : 当发生错误的时候,是否返回 None
|
|
268
|
-
"""
|
|
269
|
-
# 默认时区为 +08:00
|
|
270
|
-
default_tz = default_tz or '+08:00'
|
|
271
|
-
|
|
272
|
-
def get_tz(tz_info: Union[str, timezone]) -> timezone:
|
|
273
|
-
"""将时区信息转换为timezone对象"""
|
|
274
|
-
if isinstance(tz_info, timezone):
|
|
275
|
-
return tz_info
|
|
276
|
-
if not isinstance(tz_info, str):
|
|
277
|
-
raise ValueError(f"无效的时区格式: {tz_info}")
|
|
278
|
-
tz_str = tz_info.upper()
|
|
279
|
-
if tz_str == "UTC":
|
|
280
|
-
return timezone.utc
|
|
281
|
-
# 处理纯偏移格式,如+07:00、-05:30
|
|
282
|
-
offset_match = re.match(r"^([+-])(\d{1,2}):(\d{2})$", tz_str)
|
|
283
|
-
if offset_match:
|
|
284
|
-
sign = offset_match.group(1)
|
|
285
|
-
hours = int(offset_match.group(2))
|
|
286
|
-
minutes = int(offset_match.group(3))
|
|
287
|
-
# 计算总偏移小时数
|
|
288
|
-
total_hours = hours + minutes / 60
|
|
289
|
-
if sign == "-":
|
|
290
|
-
total_hours = -total_hours
|
|
291
|
-
return timezone(timedelta(hours=total_hours))
|
|
292
|
-
# 处理GMT格式,如GMT+08:00或GMT-5
|
|
293
|
-
gmt_match = re.match(r"GMT([+-]\d{1,2})(:\d{2})?$", tz_str)
|
|
294
|
-
if gmt_match:
|
|
295
|
-
hours = int(gmt_match.group(1))
|
|
296
|
-
return timezone(timedelta(hours=hours))
|
|
297
|
-
# 处理UTC格式,如UTC+8或UTC-05:00
|
|
298
|
-
utc_match = re.match(r"UTC([+-]\d{1,2})(:\d{2})?$", tz_str)
|
|
299
|
-
if utc_match:
|
|
300
|
-
hours = int(utc_match.group(1))
|
|
301
|
-
return timezone(timedelta(hours=hours))
|
|
302
|
-
raise ValueError(f"不支持的时区格式: {tz_info}")
|
|
303
|
-
|
|
304
|
-
use_default_time = False
|
|
305
|
-
if s is None or s == '':
|
|
306
|
-
dt = datetime.now(get_tz(default_tz))
|
|
307
|
-
else:
|
|
308
|
-
s = str(s).strip()
|
|
309
|
-
dt = None
|
|
310
|
-
|
|
311
|
-
# 1. 尝试解析时间戳
|
|
312
|
-
if re.match(r"^\d{1,19}$", s):
|
|
313
|
-
timestamp = int(s)
|
|
314
|
-
if len(s) > 10: # 毫秒级时间戳
|
|
315
|
-
timestamp = timestamp // 1000
|
|
316
|
-
# 先转为无时区的 datetime
|
|
317
|
-
dt = datetime.fromtimestamp(timestamp)
|
|
318
|
-
dt = dt.replace(tzinfo=get_tz(default_tz))
|
|
319
|
-
|
|
320
|
-
# 2. 尝试解析 ISO 8601 格式
|
|
321
|
-
if dt is None:
|
|
322
|
-
try:
|
|
323
|
-
dt = datetime.fromisoformat(s)
|
|
324
|
-
except ValueError:
|
|
325
|
-
pass
|
|
326
|
-
|
|
327
|
-
# 3. 尝试解析带GMT时区的格式,如'2025/09/16 17:32:17.896 GMT+08:00'
|
|
328
|
-
if dt is None:
|
|
329
|
-
gmt_pattern = r"^(\d{4})[/-](\d{2})[/-](\d{2}) (\d{2}):(\d{2}):(\d{2})(\.\d+)? (GMT[+-]\d{1,2}(:\d{2})?)$"
|
|
330
|
-
match = re.match(gmt_pattern, s)
|
|
331
|
-
if match:
|
|
332
|
-
try:
|
|
333
|
-
# 提取日期时间部分
|
|
334
|
-
year, month, day = map(int, match.group(1, 2, 3))
|
|
335
|
-
hour, minute, second = map(int, match.group(4, 5, 6))
|
|
336
|
-
microsecond = 0
|
|
337
|
-
if match.group(7):
|
|
338
|
-
# 处理毫秒/微秒部分
|
|
339
|
-
microsecond = int(float(match.group(7)) * 1e6)
|
|
340
|
-
|
|
341
|
-
# 创建datetime对象
|
|
342
|
-
dt = datetime(year, month, day, hour, minute, second, microsecond)
|
|
343
|
-
|
|
344
|
-
# 应用时区
|
|
345
|
-
tz_info = get_tz(match.group(8))
|
|
346
|
-
dt = dt.replace(tzinfo=tz_info)
|
|
347
|
-
except ValueError:
|
|
348
|
-
pass
|
|
349
|
-
|
|
350
|
-
# 4. 使用指定的pattern解析
|
|
351
|
-
if dt is None and pattern is not None:
|
|
352
|
-
try:
|
|
353
|
-
# 移除可能的毫秒部分
|
|
354
|
-
s_without_ms = s.split('.')[0]
|
|
355
|
-
dt = datetime.strptime(s_without_ms, pattern)
|
|
356
|
-
except ValueError:
|
|
357
|
-
pass
|
|
358
|
-
|
|
359
|
-
# 5. 尝试解析YYYY-MM-DD HH:MM:SS或YYYY/MM/DD HH:MM:SS格式
|
|
360
|
-
if dt is None:
|
|
361
|
-
# 尝试处理不带时区的格式
|
|
362
|
-
formats = ["%Y-%m-%d %H:%M:%S", "%Y/%m/%d %H:%M:%S"]
|
|
363
|
-
for fmt in formats:
|
|
364
|
-
try:
|
|
365
|
-
# 移除可能的毫秒和时区部分
|
|
366
|
-
s_clean = re.sub(r"(\.\d+)|[TZ]|GMT.*$", " ", s).strip()
|
|
367
|
-
dt = datetime.strptime(s_clean, fmt)
|
|
368
|
-
break
|
|
369
|
-
except ValueError:
|
|
370
|
-
continue
|
|
371
|
-
|
|
372
|
-
if dt is None:
|
|
373
|
-
use_default_time = True
|
|
374
|
-
dt = datetime.now()
|
|
375
|
-
|
|
376
|
-
# 确保无时区时附加默认时区
|
|
377
|
-
if dt.tzinfo is None:
|
|
378
|
-
dt = dt.replace(tzinfo=get_tz(default_tz))
|
|
379
|
-
|
|
380
|
-
# 转换为目标时区
|
|
381
|
-
if tz is not None:
|
|
382
|
-
dt = dt.astimezone(get_tz(tz))
|
|
383
|
-
|
|
384
|
-
if error_is_none and use_default_time:
|
|
385
|
-
return None
|
|
386
|
-
|
|
387
|
-
return dt.isoformat() if r_str else dt
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
# 将字符串 s 转化成 datetime, 然后再次转化成 str
|
|
391
|
-
def to_datetime_str(s: Any = None,
|
|
392
|
-
pattern: str = None,
|
|
393
|
-
pattern_str: str = None,
|
|
394
|
-
tz: Optional[Union[str, timezone]] = None,
|
|
395
|
-
default_tz: Union[str, timezone] = None) -> datetime | str:
|
|
396
|
-
"""
|
|
397
|
-
将 s 先转成 datetime, 然后再转成字符串
|
|
398
|
-
|
|
399
|
-
:param s: 输入值(可以是字符串或其他类型)
|
|
400
|
-
"""
|
|
401
|
-
r_s = to_datetime(s, pattern=pattern, tz=tz, r_str=False, default_tz=default_tz)
|
|
402
|
-
if pattern_str is None:
|
|
403
|
-
iso_str = r_s.isoformat()
|
|
404
|
-
if '.' not in iso_str:
|
|
405
|
-
# '2025-10-09T10:52:41+08:00'
|
|
406
|
-
return iso_str
|
|
407
|
-
parts = iso_str.split('.')
|
|
408
|
-
time_zone_part = parts[1]
|
|
409
|
-
time_zone_str = tz
|
|
410
|
-
millisecond_part = time_zone_part[:3]
|
|
411
|
-
for a in ['+', '-']:
|
|
412
|
-
if a in time_zone_part:
|
|
413
|
-
time_zone_str = a + time_zone_part.split(a)[-1]
|
|
414
|
-
return parts[0] + '.' + millisecond_part + time_zone_str
|
|
415
|
-
else:
|
|
416
|
-
return r_s.strftime(pattern_str)
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
def to_datetime_format(s: Any = None,
|
|
420
|
-
pattern_str: str = "%Y-%m-%d %H:%M:%S") -> datetime | str:
|
|
421
|
-
return to_datetime_str(s, pattern=None, pattern_str=pattern_str, tz=None)
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
def to_datetime_format__6(s: Any = None,
|
|
425
|
-
pattern_str: str = "%Y-%m-%d %H:%M:%S") -> datetime | str:
|
|
426
|
-
return to_datetime_str(s, pattern=None, pattern_str=pattern_str, tz='-06:00')
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
def to_datetime_format_7(s: Any = None,
|
|
430
|
-
pattern_str: str = "%Y-%m-%d %H:%M:%S") -> datetime | str:
|
|
431
|
-
return to_datetime_str(s, pattern=None, pattern_str=pattern_str, tz='+07:00')
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
def to_datetime_format_8(s: Any = None,
|
|
435
|
-
pattern_str: str = "%Y-%m-%d %H:%M:%S") -> datetime | str:
|
|
436
|
-
return to_datetime_str(s, pattern=None, pattern_str=pattern_str, tz='+08:00')
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
# 时间加减
|
|
440
|
-
def to_datetime_add(s: Any = None,
|
|
441
|
-
days: int = 0,
|
|
442
|
-
seconds: int = 0,
|
|
443
|
-
microseconds: int = 0,
|
|
444
|
-
milliseconds: int = 0,
|
|
445
|
-
minutes: int = 0,
|
|
446
|
-
hours: int = 0,
|
|
447
|
-
weeks: int = 0) -> datetime:
|
|
448
|
-
return to_datetime(s) + timedelta(days=days, seconds=seconds, microseconds=microseconds,
|
|
449
|
-
milliseconds=milliseconds, minutes=minutes, hours=hours,
|
|
450
|
-
weeks=weeks)
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
# 将字符串 s 转化成 date 例如: 2021-02-03
|
|
454
|
-
def to_date(s: Any = None) -> str:
|
|
455
|
-
return str(to_datetime(s))[0:10]
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
# 将字符串 s 转化成 date 例如: 20210203
|
|
459
|
-
def to_date_number(s: Any = None) -> str:
|
|
460
|
-
return str(to_datetime(s))[0:10].replace('-', '')
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
def get_timestamp(s: Any = None) -> int:
|
|
464
|
-
"""获取 Unix 秒级时间戳"""
|
|
465
|
-
return int(to_datetime(s).timestamp())
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
def get_datetime_number_str(s: Any = None,
|
|
469
|
-
length: int = None,
|
|
470
|
-
remove_dz: bool = True,
|
|
471
|
-
) -> str:
|
|
472
|
-
"""获取 datetime , 然后转成字符串, 然后, 只保留数字
|
|
473
|
-
Args:
|
|
474
|
-
s: 输入值,可以是任何类型,如果是None则使用当前时间
|
|
475
|
-
length: 可选参数,指定返回字符串的长度
|
|
476
|
-
remove_dz: 是否去掉时区
|
|
477
|
-
Returns:
|
|
478
|
-
str: 只包含数字的字符串
|
|
479
|
-
"""
|
|
480
|
-
s1 = to_datetime(s)
|
|
481
|
-
digits_only = re.sub(r'\D', '', str(s1))
|
|
482
|
-
# 如果指定了长度,取最后length位
|
|
483
|
-
if length is not None and length > 0:
|
|
484
|
-
return digits_only[-length:] if len(digits_only) > length else digits_only
|
|
485
|
-
if len(digits_only) > 4 and remove_dz:
|
|
486
|
-
digits_only = digits_only[:-4]
|
|
487
|
-
return digits_only
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
def get_timestamp_ms(s: Any = None) -> int:
|
|
491
|
-
"""获取 Unix 毫秒级时间戳"""
|
|
492
|
-
return int(to_datetime(s).timestamp() * 1000)
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
# 时间加减
|
|
496
|
-
def to_date_add(s: Any = None,
|
|
497
|
-
days: int = 0,
|
|
498
|
-
seconds: int = 0,
|
|
499
|
-
microseconds: int = 0,
|
|
500
|
-
milliseconds: int = 0,
|
|
501
|
-
minutes: int = 0,
|
|
502
|
-
hours: int = 0,
|
|
503
|
-
weeks: int = 0) -> str:
|
|
504
|
-
return str(to_datetime_add(s=s, days=days, seconds=seconds, microseconds=microseconds,
|
|
505
|
-
milliseconds=milliseconds, minutes=minutes, hours=hours, weeks=weeks))[0:10]
|
|
506
|
-
|
|
507
|
-
|
|
508
256
|
# 转化成字符串
|
|
509
257
|
def to_str(param: Any = None) -> str:
|
|
510
258
|
return json.dumps(param, ensure_ascii=False) if is_json_serializable(param) else str(param)
|
|
@@ -8,8 +8,9 @@ upplib/chart_html.py
|
|
|
8
8
|
upplib/clean_up_msg.py
|
|
9
9
|
upplib/common_package.py
|
|
10
10
|
upplib/config_data.py
|
|
11
|
+
upplib/datetime_function.py
|
|
11
12
|
upplib/db.py
|
|
12
|
-
upplib/
|
|
13
|
+
upplib/file_function.py
|
|
13
14
|
upplib/file_to_text.py
|
|
14
15
|
upplib/format_data.py
|
|
15
16
|
upplib/http_util.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|