staran 1.0.9__py3-none-any.whl → 1.0.10__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.
- staran/__init__.py +0 -62
- staran/date/__init__.py +72 -87
- staran/date/core/__init__.py +24 -0
- staran/date/{core.py → core/core.py} +539 -8
- staran/date/examples/v1010_features_demo.py +376 -0
- staran/date/extensions/__init__.py +48 -0
- staran/date/extensions/expressions.py +554 -0
- staran/date/extensions/solar_terms.py +417 -0
- staran/date/extensions/timezone.py +263 -0
- staran/date/integrations/__init__.py +38 -0
- staran/date/integrations/api_server.py +754 -0
- staran/date/integrations/visualization.py +689 -0
- staran/date/tests/test_v1010_features.py +495 -0
- {staran-1.0.9.dist-info → staran-1.0.10.dist-info}/METADATA +34 -8
- staran-1.0.10.dist-info/RECORD +34 -0
- staran-1.0.10.dist-info/entry_points.txt +2 -0
- staran-1.0.9.dist-info/RECORD +0 -23
- /staran/date/{i18n.py → core/i18n.py} +0 -0
- /staran/date/{lunar.py → core/lunar.py} +0 -0
- {staran-1.0.9.dist-info → staran-1.0.10.dist-info}/WHEEL +0 -0
- {staran-1.0.9.dist-info → staran-1.0.10.dist-info}/licenses/LICENSE +0 -0
- {staran-1.0.9.dist-info → staran-1.0.10.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,495 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
"""
|
5
|
+
Date类v1.0.10新功能测试
|
6
|
+
======================
|
7
|
+
|
8
|
+
测试v1.0.10版本新增的功能:
|
9
|
+
- 时区支持
|
10
|
+
- 日期表达式解析
|
11
|
+
- 二十四节气
|
12
|
+
- 数据可视化
|
13
|
+
- 增强日期范围操作
|
14
|
+
"""
|
15
|
+
|
16
|
+
import unittest
|
17
|
+
import datetime
|
18
|
+
import sys
|
19
|
+
import os
|
20
|
+
|
21
|
+
# 添加项目根目录到路径
|
22
|
+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..'))
|
23
|
+
|
24
|
+
from staran.date.core.core import Date, DateRange
|
25
|
+
from staran.date import get_version_info, parse_expression
|
26
|
+
|
27
|
+
class TestV1010TimezoneSupport(unittest.TestCase):
|
28
|
+
"""测试时区支持功能"""
|
29
|
+
|
30
|
+
def setUp(self):
|
31
|
+
self.date = Date("2025-07-29")
|
32
|
+
|
33
|
+
def test_get_supported_timezones(self):
|
34
|
+
"""测试获取支持的时区"""
|
35
|
+
try:
|
36
|
+
timezones = Date.get_supported_timezones()
|
37
|
+
self.assertIsInstance(timezones, list)
|
38
|
+
if timezones: # 如果功能可用
|
39
|
+
self.assertIn('UTC', timezones)
|
40
|
+
self.assertIn('UTC+8', timezones)
|
41
|
+
except NotImplementedError:
|
42
|
+
self.skipTest("时区功能不可用")
|
43
|
+
|
44
|
+
def test_get_timezone_info(self):
|
45
|
+
"""测试获取时区信息"""
|
46
|
+
try:
|
47
|
+
tz_info = self.date.get_timezone_info('UTC+8')
|
48
|
+
self.assertIsInstance(tz_info, dict)
|
49
|
+
self.assertIn('name', tz_info)
|
50
|
+
self.assertIn('current_offset', tz_info)
|
51
|
+
self.assertIn('offset_string', tz_info)
|
52
|
+
except NotImplementedError:
|
53
|
+
self.skipTest("时区功能不可用")
|
54
|
+
|
55
|
+
def test_timezone_conversion(self):
|
56
|
+
"""测试时区转换"""
|
57
|
+
try:
|
58
|
+
time_part = datetime.time(12, 0, 0)
|
59
|
+
result = self.date.to_timezone('UTC+8', time_part)
|
60
|
+
self.assertIsInstance(result, datetime.datetime)
|
61
|
+
self.assertEqual(result.date(), self.date.to_date_object())
|
62
|
+
except NotImplementedError:
|
63
|
+
self.skipTest("时区功能不可用")
|
64
|
+
|
65
|
+
class TestV1010ExpressionParsing(unittest.TestCase):
|
66
|
+
"""测试日期表达式解析功能"""
|
67
|
+
|
68
|
+
def test_simple_expressions(self):
|
69
|
+
"""测试简单表达式"""
|
70
|
+
try:
|
71
|
+
# 基本表达式
|
72
|
+
today = Date.today()
|
73
|
+
|
74
|
+
tomorrow = parse_expression("明天")
|
75
|
+
if tomorrow: # 如果功能可用
|
76
|
+
expected_tomorrow = today.add_days(1)
|
77
|
+
self.assertEqual(tomorrow.to_date_object(), expected_tomorrow.to_date_object())
|
78
|
+
|
79
|
+
yesterday = parse_expression("昨天")
|
80
|
+
if yesterday:
|
81
|
+
expected_yesterday = today.add_days(-1)
|
82
|
+
self.assertEqual(yesterday.to_date_object(), expected_yesterday.to_date_object())
|
83
|
+
except NotImplementedError:
|
84
|
+
self.skipTest("表达式解析功能不可用")
|
85
|
+
|
86
|
+
def test_detailed_parsing(self):
|
87
|
+
"""测试详细解析"""
|
88
|
+
try:
|
89
|
+
result = Date.parse_expression_detailed("明天")
|
90
|
+
self.assertIsInstance(result, dict)
|
91
|
+
self.assertIn('success', result)
|
92
|
+
self.assertIn('confidence', result)
|
93
|
+
self.assertIn('matched_pattern', result)
|
94
|
+
except NotImplementedError:
|
95
|
+
self.skipTest("表达式解析功能不可用")
|
96
|
+
|
97
|
+
def test_expression_matching(self):
|
98
|
+
"""测试表达式匹配"""
|
99
|
+
try:
|
100
|
+
today = Date.today()
|
101
|
+
self.assertTrue(today.matches_expression("今天"))
|
102
|
+
except NotImplementedError:
|
103
|
+
self.skipTest("表达式解析功能不可用")
|
104
|
+
|
105
|
+
class TestV1010SolarTerms(unittest.TestCase):
|
106
|
+
"""测试二十四节气功能"""
|
107
|
+
|
108
|
+
def setUp(self):
|
109
|
+
self.date = Date("2025-07-29")
|
110
|
+
self.year = 2025
|
111
|
+
|
112
|
+
def test_get_year_solar_terms(self):
|
113
|
+
"""测试获取年份节气"""
|
114
|
+
try:
|
115
|
+
terms = Date.get_year_solar_terms(self.year)
|
116
|
+
self.assertIsInstance(terms, list)
|
117
|
+
if terms: # 如果功能可用
|
118
|
+
self.assertEqual(len(terms), 24)
|
119
|
+
# 检查第一个节气
|
120
|
+
first_term = terms[0]
|
121
|
+
self.assertEqual(first_term.name, '立春')
|
122
|
+
except NotImplementedError:
|
123
|
+
self.skipTest("节气功能不可用")
|
124
|
+
|
125
|
+
def test_get_season_solar_terms(self):
|
126
|
+
"""测试获取季节节气"""
|
127
|
+
try:
|
128
|
+
spring_terms = Date.get_season_solar_terms(self.year, '春季')
|
129
|
+
self.assertIsInstance(spring_terms, list)
|
130
|
+
if spring_terms: # 如果功能可用
|
131
|
+
self.assertEqual(len(spring_terms), 6)
|
132
|
+
self.assertEqual(spring_terms[0].name, '立春')
|
133
|
+
except NotImplementedError:
|
134
|
+
self.skipTest("节气功能不可用")
|
135
|
+
|
136
|
+
def test_solar_term_queries(self):
|
137
|
+
"""测试节气查询"""
|
138
|
+
try:
|
139
|
+
# 获取当前最近节气
|
140
|
+
current_term = self.date.get_solar_term()
|
141
|
+
if current_term: # 如果功能可用
|
142
|
+
self.assertIsNotNone(current_term.name)
|
143
|
+
self.assertIsNotNone(current_term.season)
|
144
|
+
|
145
|
+
# 获取下一个节气
|
146
|
+
next_term = self.date.get_next_solar_term()
|
147
|
+
if next_term:
|
148
|
+
self.assertIsNotNone(next_term.name)
|
149
|
+
|
150
|
+
# 获取上一个节气
|
151
|
+
prev_term = self.date.get_previous_solar_term()
|
152
|
+
if prev_term:
|
153
|
+
self.assertIsNotNone(prev_term.name)
|
154
|
+
|
155
|
+
# 到下个节气的天数
|
156
|
+
days = self.date.days_to_next_solar_term()
|
157
|
+
self.assertIsInstance(days, int)
|
158
|
+
self.assertGreaterEqual(days, 0)
|
159
|
+
|
160
|
+
except NotImplementedError:
|
161
|
+
self.skipTest("节气功能不可用")
|
162
|
+
|
163
|
+
def test_is_solar_term(self):
|
164
|
+
"""测试是否节气日"""
|
165
|
+
try:
|
166
|
+
is_term = self.date.is_solar_term()
|
167
|
+
self.assertIsInstance(is_term, bool)
|
168
|
+
except NotImplementedError:
|
169
|
+
self.skipTest("节气功能不可用")
|
170
|
+
|
171
|
+
def test_solar_term_season(self):
|
172
|
+
"""测试获取节气季节"""
|
173
|
+
try:
|
174
|
+
season = self.date.get_solar_term_season()
|
175
|
+
self.assertIsInstance(season, str)
|
176
|
+
except NotImplementedError:
|
177
|
+
self.skipTest("节气功能不可用")
|
178
|
+
|
179
|
+
class TestV1010Visualization(unittest.TestCase):
|
180
|
+
"""测试数据可视化功能"""
|
181
|
+
|
182
|
+
def setUp(self):
|
183
|
+
self.dates = [Date("2025-07-29"), Date("2025-07-30"), Date("2025-07-31")]
|
184
|
+
self.events = ["事件1", "事件2", "事件3"]
|
185
|
+
|
186
|
+
def test_create_timeline_chart(self):
|
187
|
+
"""测试创建时间轴图表"""
|
188
|
+
try:
|
189
|
+
from staran.date import create_timeline_chart
|
190
|
+
chart_data = create_timeline_chart(self.dates, self.events, 'echarts')
|
191
|
+
|
192
|
+
self.assertIsNotNone(chart_data)
|
193
|
+
self.assertEqual(chart_data.chart_type, 'timeline')
|
194
|
+
self.assertEqual(chart_data.library, 'echarts')
|
195
|
+
self.assertIsInstance(chart_data.data, list)
|
196
|
+
except (NotImplementedError, ImportError):
|
197
|
+
self.skipTest("可视化功能不可用")
|
198
|
+
|
199
|
+
def test_create_calendar_heatmap(self):
|
200
|
+
"""测试创建日历热力图"""
|
201
|
+
try:
|
202
|
+
date_values = {
|
203
|
+
Date("2025-07-29"): 85,
|
204
|
+
Date("2025-07-30"): 92,
|
205
|
+
Date("2025-07-31"): 78
|
206
|
+
}
|
207
|
+
|
208
|
+
chart_data = Date.create_calendar_heatmap(date_values, 2025, 'echarts')
|
209
|
+
|
210
|
+
self.assertIsNotNone(chart_data)
|
211
|
+
self.assertEqual(chart_data.chart_type, 'calendar_heatmap')
|
212
|
+
self.assertEqual(chart_data.library, 'echarts')
|
213
|
+
except NotImplementedError:
|
214
|
+
self.skipTest("可视化功能不可用")
|
215
|
+
|
216
|
+
def test_create_time_series_chart(self):
|
217
|
+
"""测试创建时间序列图"""
|
218
|
+
try:
|
219
|
+
time_series_data = [
|
220
|
+
(Date("2025-07-29"), 100),
|
221
|
+
(Date("2025-07-30"), 120),
|
222
|
+
(Date("2025-07-31"), 95)
|
223
|
+
]
|
224
|
+
|
225
|
+
chart_data = Date.create_time_series_chart(time_series_data, 'echarts')
|
226
|
+
|
227
|
+
self.assertIsNotNone(chart_data)
|
228
|
+
self.assertEqual(chart_data.chart_type, 'time_series')
|
229
|
+
self.assertEqual(chart_data.library, 'echarts')
|
230
|
+
except NotImplementedError:
|
231
|
+
self.skipTest("可视化功能不可用")
|
232
|
+
|
233
|
+
def test_create_date_distribution_chart(self):
|
234
|
+
"""测试创建日期分布图"""
|
235
|
+
try:
|
236
|
+
chart_data = Date.create_date_distribution_chart(self.dates, 'month', 'echarts')
|
237
|
+
|
238
|
+
self.assertIsNotNone(chart_data)
|
239
|
+
self.assertEqual(chart_data.chart_type, 'distribution')
|
240
|
+
self.assertEqual(chart_data.library, 'echarts')
|
241
|
+
except NotImplementedError:
|
242
|
+
self.skipTest("可视化功能不可用")
|
243
|
+
|
244
|
+
class TestV1010EnhancedDateRanges(unittest.TestCase):
|
245
|
+
"""测试增强的日期范围功能"""
|
246
|
+
|
247
|
+
def setUp(self):
|
248
|
+
self.start_date = Date("2025-07-29")
|
249
|
+
self.end_date = Date("2025-08-15")
|
250
|
+
|
251
|
+
def test_create_range_to(self):
|
252
|
+
"""测试创建到指定日期的范围"""
|
253
|
+
date_range = self.start_date.create_range_to(self.end_date)
|
254
|
+
|
255
|
+
self.assertIsInstance(date_range, DateRange)
|
256
|
+
self.assertEqual(date_range.start, self.start_date)
|
257
|
+
self.assertEqual(date_range.end, self.end_date)
|
258
|
+
|
259
|
+
def test_create_range_with_days(self):
|
260
|
+
"""测试创建指定天数的范围"""
|
261
|
+
# 未来10天
|
262
|
+
future_range = self.start_date.create_range_with_days(10)
|
263
|
+
self.assertEqual(future_range.start, self.start_date)
|
264
|
+
self.assertEqual(future_range.end, self.start_date.add_days(10))
|
265
|
+
|
266
|
+
# 过去5天
|
267
|
+
past_range = self.start_date.create_range_with_days(-5)
|
268
|
+
self.assertEqual(past_range.start, self.start_date.add_days(-5))
|
269
|
+
self.assertEqual(past_range.end, self.start_date)
|
270
|
+
|
271
|
+
def test_in_range(self):
|
272
|
+
"""测试是否在范围内"""
|
273
|
+
test_date = Date("2025-08-01")
|
274
|
+
|
275
|
+
# 在范围内
|
276
|
+
self.assertTrue(test_date.in_range(self.start_date, self.end_date))
|
277
|
+
|
278
|
+
# 不在范围内
|
279
|
+
out_of_range_date = Date("2025-09-01")
|
280
|
+
self.assertFalse(out_of_range_date.in_range(self.start_date, self.end_date))
|
281
|
+
|
282
|
+
def test_create_date_sequence(self):
|
283
|
+
"""测试创建日期序列"""
|
284
|
+
sequence = Date.create_date_sequence(self.start_date, self.start_date.add_days(6), 2)
|
285
|
+
|
286
|
+
self.assertIsInstance(sequence, list)
|
287
|
+
self.assertEqual(len(sequence), 4) # 0, 2, 4, 6天
|
288
|
+
self.assertEqual(sequence[0], self.start_date)
|
289
|
+
self.assertEqual(sequence[1], self.start_date.add_days(2))
|
290
|
+
|
291
|
+
def test_find_common_dates(self):
|
292
|
+
"""测试查找共同日期"""
|
293
|
+
list1 = [Date("2025-07-29"), Date("2025-07-30"), Date("2025-07-31")]
|
294
|
+
list2 = [Date("2025-07-30"), Date("2025-07-31"), Date("2025-08-01")]
|
295
|
+
list3 = [Date("2025-07-31"), Date("2025-08-01"), Date("2025-08-02")]
|
296
|
+
|
297
|
+
common_dates = Date.find_common_dates([list1, list2, list3])
|
298
|
+
|
299
|
+
self.assertIsInstance(common_dates, list)
|
300
|
+
self.assertEqual(len(common_dates), 1)
|
301
|
+
self.assertEqual(common_dates[0], Date("2025-07-31"))
|
302
|
+
|
303
|
+
class TestV1010UtilityMethods(unittest.TestCase):
|
304
|
+
"""测试v1.0.10实用工具方法"""
|
305
|
+
|
306
|
+
def setUp(self):
|
307
|
+
self.date = Date("2025-07-29")
|
308
|
+
|
309
|
+
def test_get_version_info(self):
|
310
|
+
"""测试获取版本信息"""
|
311
|
+
version_info = self.date.get_version_info()
|
312
|
+
|
313
|
+
self.assertIsInstance(version_info, dict)
|
314
|
+
self.assertIn('version', version_info)
|
315
|
+
self.assertEqual(version_info['version'], '1.0.10')
|
316
|
+
self.assertIn('enhanced_features', version_info)
|
317
|
+
self.assertIn('available_modules', version_info)
|
318
|
+
self.assertIn('api_count', version_info)
|
319
|
+
|
320
|
+
def test_get_feature_status(self):
|
321
|
+
"""测试获取功能状态"""
|
322
|
+
feature_status = Date.get_feature_status()
|
323
|
+
|
324
|
+
self.assertIsInstance(feature_status, dict)
|
325
|
+
self.assertIn('core_date_operations', feature_status)
|
326
|
+
self.assertTrue(feature_status['core_date_operations'])
|
327
|
+
self.assertIn('lunar_calendar', feature_status)
|
328
|
+
self.assertTrue(feature_status['lunar_calendar'])
|
329
|
+
self.assertIn('multilingual_support', feature_status)
|
330
|
+
self.assertTrue(feature_status['multilingual_support'])
|
331
|
+
|
332
|
+
def test_help_system(self):
|
333
|
+
"""测试帮助系统"""
|
334
|
+
# 测试创建方法帮助
|
335
|
+
help_creation = self.date.help('creation')
|
336
|
+
self.assertIsInstance(help_creation, str)
|
337
|
+
self.assertIn('Date', help_creation)
|
338
|
+
|
339
|
+
# 测试格式化帮助
|
340
|
+
help_formatting = self.date.help('formatting')
|
341
|
+
self.assertIsInstance(help_formatting, str)
|
342
|
+
self.assertIn('format', help_formatting)
|
343
|
+
|
344
|
+
# 测试计算帮助
|
345
|
+
help_calculations = self.date.help('calculations')
|
346
|
+
self.assertIsInstance(help_calculations, str)
|
347
|
+
self.assertIn('add_days', help_calculations)
|
348
|
+
|
349
|
+
# 测试全部帮助
|
350
|
+
help_all = self.date.help('all')
|
351
|
+
self.assertIsInstance(help_all, str)
|
352
|
+
self.assertIn('Date', help_all)
|
353
|
+
|
354
|
+
class TestV1010Integration(unittest.TestCase):
|
355
|
+
"""测试v1.0.10集成功能"""
|
356
|
+
|
357
|
+
def test_version_consistency(self):
|
358
|
+
"""测试版本一致性"""
|
359
|
+
from staran.date import __version__, get_version_info
|
360
|
+
|
361
|
+
# 检查模块版本
|
362
|
+
self.assertEqual(__version__, "1.0.10")
|
363
|
+
|
364
|
+
# 检查版本信息函数
|
365
|
+
version_info = get_version_info()
|
366
|
+
self.assertEqual(version_info['version'], "1.0.10")
|
367
|
+
|
368
|
+
def test_backwards_compatibility(self):
|
369
|
+
"""测试向后兼容性"""
|
370
|
+
# 确保所有v1.0.8和v1.0.9的功能仍然可用
|
371
|
+
date = Date("2025-07-29")
|
372
|
+
|
373
|
+
# 基础功能
|
374
|
+
self.assertEqual(date.format_iso(), "2025-07-29")
|
375
|
+
self.assertEqual(date.format_chinese(), "2025年07月29日")
|
376
|
+
|
377
|
+
# 农历功能
|
378
|
+
lunar = date.to_lunar()
|
379
|
+
self.assertIsNotNone(lunar)
|
380
|
+
|
381
|
+
# 多语言功能
|
382
|
+
Date.set_language('zh_CN')
|
383
|
+
localized = date.format_localized()
|
384
|
+
self.assertIsInstance(localized, str)
|
385
|
+
|
386
|
+
# 计算功能
|
387
|
+
tomorrow = date.add_days(1)
|
388
|
+
self.assertEqual(tomorrow.to_date_object(), datetime.date(2025, 7, 30))
|
389
|
+
|
390
|
+
def test_api_count_increase(self):
|
391
|
+
"""测试API数量增加"""
|
392
|
+
date = Date("2025-07-29")
|
393
|
+
version_info = date.get_version_info()
|
394
|
+
|
395
|
+
# v1.0.10应该比之前版本有更多API
|
396
|
+
api_count = version_info['api_count']
|
397
|
+
self.assertGreater(api_count, 120) # 应该超过120个API方法
|
398
|
+
|
399
|
+
# 测试运行器
|
400
|
+
class TestV1010Runner:
|
401
|
+
"""v1.0.10测试运行器"""
|
402
|
+
|
403
|
+
@staticmethod
|
404
|
+
def run_all_tests():
|
405
|
+
"""运行所有v1.0.10测试"""
|
406
|
+
loader = unittest.TestLoader()
|
407
|
+
suite = unittest.TestSuite()
|
408
|
+
|
409
|
+
# 添加所有测试类
|
410
|
+
test_classes = [
|
411
|
+
TestV1010TimezoneSupport,
|
412
|
+
TestV1010ExpressionParsing,
|
413
|
+
TestV1010SolarTerms,
|
414
|
+
TestV1010Visualization,
|
415
|
+
TestV1010EnhancedDateRanges,
|
416
|
+
TestV1010UtilityMethods,
|
417
|
+
TestV1010Integration
|
418
|
+
]
|
419
|
+
|
420
|
+
for test_class in test_classes:
|
421
|
+
tests = loader.loadTestsFromTestCase(test_class)
|
422
|
+
suite.addTests(tests)
|
423
|
+
|
424
|
+
# 运行测试
|
425
|
+
runner = unittest.TextTestRunner(verbosity=2)
|
426
|
+
result = runner.run(suite)
|
427
|
+
|
428
|
+
return result
|
429
|
+
|
430
|
+
@staticmethod
|
431
|
+
def run_specific_test(test_class_name: str):
|
432
|
+
"""运行特定测试类"""
|
433
|
+
test_classes = {
|
434
|
+
'timezone': TestV1010TimezoneSupport,
|
435
|
+
'expressions': TestV1010ExpressionParsing,
|
436
|
+
'solar_terms': TestV1010SolarTerms,
|
437
|
+
'visualization': TestV1010Visualization,
|
438
|
+
'ranges': TestV1010EnhancedDateRanges,
|
439
|
+
'utilities': TestV1010UtilityMethods,
|
440
|
+
'integration': TestV1010Integration
|
441
|
+
}
|
442
|
+
|
443
|
+
test_class = test_classes.get(test_class_name)
|
444
|
+
if test_class:
|
445
|
+
loader = unittest.TestLoader()
|
446
|
+
suite = loader.loadTestsFromTestCase(test_class)
|
447
|
+
runner = unittest.TextTestRunner(verbosity=2)
|
448
|
+
return runner.run(suite)
|
449
|
+
else:
|
450
|
+
print(f"测试类 '{test_class_name}' 不存在")
|
451
|
+
print(f"可用的测试类: {list(test_classes.keys())}")
|
452
|
+
|
453
|
+
if __name__ == "__main__":
|
454
|
+
print("🧪 Staran v1.0.10 新功能测试")
|
455
|
+
print("=" * 50)
|
456
|
+
|
457
|
+
# 检查命令行参数
|
458
|
+
if len(sys.argv) > 1:
|
459
|
+
test_name = sys.argv[1]
|
460
|
+
print(f"运行特定测试: {test_name}")
|
461
|
+
TestV1010Runner.run_specific_test(test_name)
|
462
|
+
else:
|
463
|
+
print("运行所有v1.0.10新功能测试")
|
464
|
+
result = TestV1010Runner.run_all_tests()
|
465
|
+
|
466
|
+
# 输出结果摘要
|
467
|
+
print(f"\n" + "=" * 50)
|
468
|
+
print(f"测试摘要:")
|
469
|
+
print(f" 运行测试数: {result.testsRun}")
|
470
|
+
print(f" 失败数: {len(result.failures)}")
|
471
|
+
print(f" 错误数: {len(result.errors)}")
|
472
|
+
print(f" 跳过数: {len(result.skipped)}")
|
473
|
+
|
474
|
+
if result.failures:
|
475
|
+
print(f"\n失败的测试:")
|
476
|
+
for test, traceback in result.failures:
|
477
|
+
print(f" - {test}")
|
478
|
+
|
479
|
+
if result.errors:
|
480
|
+
print(f"\n错误的测试:")
|
481
|
+
for test, traceback in result.errors:
|
482
|
+
print(f" - {test}")
|
483
|
+
|
484
|
+
if result.skipped:
|
485
|
+
print(f"\n跳过的测试:")
|
486
|
+
for test, reason in result.skipped:
|
487
|
+
print(f" - {test}: {reason}")
|
488
|
+
|
489
|
+
success_rate = (result.testsRun - len(result.failures) - len(result.errors)) / result.testsRun * 100
|
490
|
+
print(f"\n成功率: {success_rate:.1f}%")
|
491
|
+
|
492
|
+
if result.wasSuccessful():
|
493
|
+
print("✅ 所有测试通过!")
|
494
|
+
else:
|
495
|
+
print("❌ 部分测试失败")
|
@@ -1,18 +1,21 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: staran
|
3
|
-
Version: 1.0.
|
4
|
-
Summary: staran -
|
3
|
+
Version: 1.0.10
|
4
|
+
Summary: staran - 企业级Python日期处理库
|
5
5
|
Home-page: https://github.com/starlxa/staran
|
6
6
|
Author: StarAn
|
7
7
|
Author-email: starlxa@icloud.com
|
8
8
|
License: MIT
|
9
9
|
Project-URL: Bug Reports, https://github.com/starlxa/staran/issues
|
10
10
|
Project-URL: Source, https://github.com/starlxa/staran
|
11
|
-
|
11
|
+
Project-URL: Documentation, https://github.com/starlxa/staran/blob/master/API_REFERENCE.md
|
12
|
+
Keywords: date datetime utilities time-processing lunar calendar i18n timezone visualization api
|
12
13
|
Classifier: Development Status :: 5 - Production/Stable
|
13
14
|
Classifier: Intended Audience :: Developers
|
14
15
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
15
16
|
Classifier: Topic :: Utilities
|
17
|
+
Classifier: Topic :: Software Development :: Localization
|
18
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
16
19
|
Classifier: Programming Language :: Python :: 3
|
17
20
|
Classifier: Programming Language :: Python :: 3.7
|
18
21
|
Classifier: Programming Language :: Python :: 3.8
|
@@ -21,9 +24,25 @@ Classifier: Programming Language :: Python :: 3.10
|
|
21
24
|
Classifier: Programming Language :: Python :: 3.11
|
22
25
|
Classifier: Programming Language :: Python :: 3.12
|
23
26
|
Classifier: Operating System :: OS Independent
|
27
|
+
Classifier: License :: OSI Approved :: MIT License
|
24
28
|
Requires-Python: >=3.7
|
25
29
|
Description-Content-Type: text/markdown
|
26
30
|
License-File: LICENSE
|
31
|
+
Provides-Extra: visualization
|
32
|
+
Requires-Dist: matplotlib>=3.0.0; extra == "visualization"
|
33
|
+
Requires-Dist: plotly>=5.0.0; extra == "visualization"
|
34
|
+
Provides-Extra: web
|
35
|
+
Requires-Dist: flask>=2.0.0; extra == "web"
|
36
|
+
Provides-Extra: full
|
37
|
+
Requires-Dist: matplotlib>=3.0.0; extra == "full"
|
38
|
+
Requires-Dist: plotly>=5.0.0; extra == "full"
|
39
|
+
Requires-Dist: flask>=2.0.0; extra == "full"
|
40
|
+
Provides-Extra: dev
|
41
|
+
Requires-Dist: pytest>=6.0.0; extra == "dev"
|
42
|
+
Requires-Dist: pytest-cov>=2.0.0; extra == "dev"
|
43
|
+
Requires-Dist: black>=21.0.0; extra == "dev"
|
44
|
+
Requires-Dist: flake8>=3.8.0; extra == "dev"
|
45
|
+
Requires-Dist: mypy>=0.800; extra == "dev"
|
27
46
|
Dynamic: author
|
28
47
|
Dynamic: author-email
|
29
48
|
Dynamic: classifier
|
@@ -34,6 +53,7 @@ Dynamic: keywords
|
|
34
53
|
Dynamic: license
|
35
54
|
Dynamic: license-file
|
36
55
|
Dynamic: project-url
|
56
|
+
Dynamic: provides-extra
|
37
57
|
Dynamic: requires-python
|
38
58
|
Dynamic: summary
|
39
59
|
|
@@ -48,8 +68,9 @@ Dynamic: summary
|
|
48
68
|
|
49
69
|
## 📚 文档导航
|
50
70
|
|
51
|
-
- **[API 参考文档](API_REFERENCE.md)** - 完整的API文档和使用指南
|
52
|
-
- **[更新日志](CHANGELOG.md)** - 详细的版本历史和更新记录
|
71
|
+
- **[API 参考文档](https://github.com/StarLxa/staran/tree/master/API_REFERENCE.md)** - 完整的API文档和使用指南
|
72
|
+
- **[更新日志](https://github.com/StarLxa/staran/tree/master/CHANGELOG.md)** - 详细的版本历史和更新记录
|
73
|
+
- **[PyPI包页面](https://pypi.org/project/staran/)** - 安装和版本信息
|
53
74
|
- **[快速开始](#快速开始)** - 立即开始使用
|
54
75
|
|
55
76
|
## 🚀 核心理念
|
@@ -94,6 +115,9 @@ staran/
|
|
94
115
|
### 安装
|
95
116
|
|
96
117
|
```bash
|
118
|
+
# 从PyPI安装 (推荐)
|
119
|
+
pip install staran
|
120
|
+
|
97
121
|
# 从源码安装
|
98
122
|
git clone https://github.com/StarLxa/staran.git
|
99
123
|
cd staran
|
@@ -172,8 +196,9 @@ python -m staran.date.tests.run_tests
|
|
172
196
|
|
173
197
|
## 📖 文档
|
174
198
|
|
175
|
-
- **[API参考文档](API_REFERENCE.md)** - 完整的API文档、使用指南和示例
|
176
|
-
- **[更新日志](CHANGELOG.md)** - 详细的版本历史和功能变更
|
199
|
+
- **[API参考文档](https://github.com/StarLxa/staran/tree/master/API_REFERENCE.md)** - 完整的API文档、使用指南和示例
|
200
|
+
- **[更新日志](https://github.com/StarLxa/staran/tree/master/CHANGELOG.md)** - 详细的版本历史和功能变更
|
201
|
+
- **[PyPI包页面](https://pypi.org/project/staran/)** - 安装和版本信息
|
177
202
|
|
178
203
|
## 🛠️ 开发
|
179
204
|
|
@@ -200,7 +225,8 @@ python -m staran.date.tests.run_tests
|
|
200
225
|
## 📞 支持
|
201
226
|
|
202
227
|
- **GitHub Issues**: 报告Bug和功能请求
|
203
|
-
- **文档**: [API参考文档](API_REFERENCE.md)
|
228
|
+
- **文档**: [API参考文档](https://github.com/StarLxa/staran/tree/master/API_REFERENCE.md)
|
229
|
+
- **PyPI**: [PyPI包页面](https://pypi.org/project/staran/)
|
204
230
|
- **示例**: 查看 `examples/` 目录
|
205
231
|
|
206
232
|
## 📄 许可证
|
@@ -0,0 +1,34 @@
|
|
1
|
+
staran/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
+
staran/date/__init__.py,sha256=CPVRv_g76wGRuKIoorXsqc58buoUQl5XkIqnZdugJUg,2858
|
3
|
+
staran/date/core/__init__.py,sha256=cZmvd7X36qmXUGPrf-K0xOchzPiSONv1rw1WMi1uNXA,430
|
4
|
+
staran/date/core/core.py,sha256=1rlVqJaZZh8PxlBcE8R6aJoHP27Xwvpc6DZ5Mv30RhU,88769
|
5
|
+
staran/date/core/i18n.py,sha256=bvnqhVGMYvW8Lt3W4uksJw9aRZ2l4cNAy0GiYEQy4II,14677
|
6
|
+
staran/date/core/lunar.py,sha256=JCs9EJOsfCXE4jgTkfZZw85-IKvjPbtx70CapEAy4sQ,11980
|
7
|
+
staran/date/examples/__init__.py,sha256=5q6uxzeIhPcFo64gXybEozx4E4lt8TEEibFC-dF_EV0,163
|
8
|
+
staran/date/examples/basic_usage.py,sha256=hsQZaMRR6tY9krLjmYrH7GrMkk2cGapY-bfjwsL_6YQ,4738
|
9
|
+
staran/date/examples/enhanced_features.py,sha256=KDxw1d-h3N19oidCyeHKCSMUrOtr0sP7K5YI1fsowrw,6598
|
10
|
+
staran/date/examples/v1010_features_demo.py,sha256=KvqfUsM3KV9kMjM2eNvGMjIdLVnRo1pYRYfLeOFH974,13342
|
11
|
+
staran/date/examples/v108_features_demo.py,sha256=E3lxnSY7nKVOi2uVl7Rb8-mxQNetBkg4PiWnV4ydmMs,9380
|
12
|
+
staran/date/examples/v109_features_demo.py,sha256=AJJu2VUKeb-GTgCHCRf4nuX9XpGwJuScxhvg2xJgJgg,9994
|
13
|
+
staran/date/extensions/__init__.py,sha256=bHkUYgwSg7FmudxLZc7185NXuxX7skMJDp69fWbEKwg,998
|
14
|
+
staran/date/extensions/expressions.py,sha256=B-p_17sGWmQfD0RVA_-_NnXvKSNgCGd2HFrH2qdlSDE,21865
|
15
|
+
staran/date/extensions/solar_terms.py,sha256=4DUNswNIOvXzIy3Q9i11MitiMoLu59Ru2S3GKnYKmfM,16007
|
16
|
+
staran/date/extensions/timezone.py,sha256=CP7kFc96CWO0RGMDF6bmVmUOoL8x9gr7YQdV8Wi5564,11182
|
17
|
+
staran/date/integrations/__init__.py,sha256=WUDNgOpktaciTylh7ftQTAgM-ROUgzbCzSajF-BEVJs,837
|
18
|
+
staran/date/integrations/api_server.py,sha256=5gV-TFkZY0sj0CA-QIWxMgoDOm1U-Dc6lC0dLMwIqxI,31097
|
19
|
+
staran/date/integrations/visualization.py,sha256=B-ZS0jjqW-sIgMBxrmGDOa8LhJS5vNol3NNLJvLNetY,23666
|
20
|
+
staran/date/tests/__init__.py,sha256=oYQFFa4lv_68398OrMGk4CMX_4XX-9KuPHTflhkLmbo,171
|
21
|
+
staran/date/tests/run_tests.py,sha256=XY8dH_zFgyQ84YAd-49sok1F8VnOsNGB_TpbJex6HKA,5842
|
22
|
+
staran/date/tests/test_core.py,sha256=IqiLjlvTBcXmajyFZDIkvh9cxT6ivQ6QFao1cXKx0w8,16539
|
23
|
+
staran/date/tests/test_enhancements.py,sha256=Iv7vr_RkHV9kgSdTKWyiAx5zbsJXf-ZLv9ytlp5TtZo,9892
|
24
|
+
staran/date/tests/test_v1010_features.py,sha256=VGWwvUtal0IfwGkIjzTCWlSGgeZrljaeJdK9f2a68X0,18266
|
25
|
+
staran/date/tests/test_v108_features.py,sha256=wih6mY-fgq1aEYdvXkFqzoeSk73-8Mf9WVe7DFjvyqE,13462
|
26
|
+
staran/date/tests/test_v109_features.py,sha256=hN5m3DTQM8j_U9ilh3fN3cQvBZH4DPI7stGlsgdIEEw,10932
|
27
|
+
staran/date/utils/__init__.py,sha256=W5DkeslSOINF7kq6wFz3l16fUmGI0XALNuJAALQeLLM,142
|
28
|
+
staran/date/utils/helpers.py,sha256=9TlebdCr-YD4vrXjTFMXDG413gbSFwdUNyivAarIp5M,5553
|
29
|
+
staran-1.0.10.dist-info/licenses/LICENSE,sha256=2EmsBIyDCono4iVXNpv5_px9qt2b7hfPq1WuyGVMNP4,1361
|
30
|
+
staran-1.0.10.dist-info/METADATA,sha256=9FVvrpHWubF7sAn2YOSib0wyaghDys9_ao9A1z5s1Us,8012
|
31
|
+
staran-1.0.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
32
|
+
staran-1.0.10.dist-info/entry_points.txt,sha256=igvLxDd-ONmb_m9IwbFKMv_uMhAyb_nPfNIq3J3rZUg,54
|
33
|
+
staran-1.0.10.dist-info/top_level.txt,sha256=NOUZtXSh5oSIEjHrC0lQ9WmoKtD010Q00dghWyag-Zs,7
|
34
|
+
staran-1.0.10.dist-info/RECORD,,
|
staran-1.0.9.dist-info/RECORD
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
staran/__init__.py,sha256=lbTKJOdoI1vk57NppCMP2iDCncsgl3-Bk9sa5oln9ro,1172
|
2
|
-
staran/date/__init__.py,sha256=ksZST17hK2eZ3ImS4U2wIai-iGarsdTHRmtLHDNTGyI,2106
|
3
|
-
staran/date/core.py,sha256=vKxSDTTNQrB8Srte2mCpZeNSOtEk2fzN7b4Abexmtao,70470
|
4
|
-
staran/date/i18n.py,sha256=bvnqhVGMYvW8Lt3W4uksJw9aRZ2l4cNAy0GiYEQy4II,14677
|
5
|
-
staran/date/lunar.py,sha256=JCs9EJOsfCXE4jgTkfZZw85-IKvjPbtx70CapEAy4sQ,11980
|
6
|
-
staran/date/examples/__init__.py,sha256=5q6uxzeIhPcFo64gXybEozx4E4lt8TEEibFC-dF_EV0,163
|
7
|
-
staran/date/examples/basic_usage.py,sha256=hsQZaMRR6tY9krLjmYrH7GrMkk2cGapY-bfjwsL_6YQ,4738
|
8
|
-
staran/date/examples/enhanced_features.py,sha256=KDxw1d-h3N19oidCyeHKCSMUrOtr0sP7K5YI1fsowrw,6598
|
9
|
-
staran/date/examples/v108_features_demo.py,sha256=E3lxnSY7nKVOi2uVl7Rb8-mxQNetBkg4PiWnV4ydmMs,9380
|
10
|
-
staran/date/examples/v109_features_demo.py,sha256=AJJu2VUKeb-GTgCHCRf4nuX9XpGwJuScxhvg2xJgJgg,9994
|
11
|
-
staran/date/tests/__init__.py,sha256=oYQFFa4lv_68398OrMGk4CMX_4XX-9KuPHTflhkLmbo,171
|
12
|
-
staran/date/tests/run_tests.py,sha256=XY8dH_zFgyQ84YAd-49sok1F8VnOsNGB_TpbJex6HKA,5842
|
13
|
-
staran/date/tests/test_core.py,sha256=IqiLjlvTBcXmajyFZDIkvh9cxT6ivQ6QFao1cXKx0w8,16539
|
14
|
-
staran/date/tests/test_enhancements.py,sha256=Iv7vr_RkHV9kgSdTKWyiAx5zbsJXf-ZLv9ytlp5TtZo,9892
|
15
|
-
staran/date/tests/test_v108_features.py,sha256=wih6mY-fgq1aEYdvXkFqzoeSk73-8Mf9WVe7DFjvyqE,13462
|
16
|
-
staran/date/tests/test_v109_features.py,sha256=hN5m3DTQM8j_U9ilh3fN3cQvBZH4DPI7stGlsgdIEEw,10932
|
17
|
-
staran/date/utils/__init__.py,sha256=W5DkeslSOINF7kq6wFz3l16fUmGI0XALNuJAALQeLLM,142
|
18
|
-
staran/date/utils/helpers.py,sha256=9TlebdCr-YD4vrXjTFMXDG413gbSFwdUNyivAarIp5M,5553
|
19
|
-
staran-1.0.9.dist-info/licenses/LICENSE,sha256=2EmsBIyDCono4iVXNpv5_px9qt2b7hfPq1WuyGVMNP4,1361
|
20
|
-
staran-1.0.9.dist-info/METADATA,sha256=xsPPTospviLkXHJTN3eqZFs6gT6RNcmY5gmOhdZBjL4,6585
|
21
|
-
staran-1.0.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
22
|
-
staran-1.0.9.dist-info/top_level.txt,sha256=NOUZtXSh5oSIEjHrC0lQ9WmoKtD010Q00dghWyag-Zs,7
|
23
|
-
staran-1.0.9.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|