docdsl 0.0.1__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.
- docdsl/__init__.py +19 -0
- docdsl/commands.py +338 -0
- docdsl/dsl_builtins.py +119 -0
- docdsl/dtformats.py +190 -0
- docdsl/exceptions.py +201 -0
- docdsl/grammar.py +208 -0
- docdsl/parser.py +77 -0
- docdsl/text_to_regex.py +266 -0
- docdsl/translator.py +94 -0
- docdsl-0.0.1.dist-info/METADATA +179 -0
- docdsl-0.0.1.dist-info/RECORD +14 -0
- docdsl-0.0.1.dist-info/WHEEL +5 -0
- docdsl-0.0.1.dist-info/licenses/LICENSE +22 -0
- docdsl-0.0.1.dist-info/top_level.txt +1 -0
docdsl/__init__.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""
|
|
2
|
+
File: __init__.py
|
|
3
|
+
Project: Docdsl
|
|
4
|
+
File Created: Wed 15 Jul 2026 08:07:46 (Shine Jayakumar)
|
|
5
|
+
Author: Shine Jayakumar (shinejayakumar@yahoo.com)
|
|
6
|
+
-----
|
|
7
|
+
Last Modified: Wed 15 Jul 2026 08:07:46 (Shine Jayakumar)
|
|
8
|
+
Modified By: Shine Jayakumar (shinejayakumar@yahoo.com)
|
|
9
|
+
-----
|
|
10
|
+
Copyright (c) 2026 Shine Jayakumar
|
|
11
|
+
SPDX-License-Identifier: MIT
|
|
12
|
+
|
|
13
|
+
Licensed under the MIT License.
|
|
14
|
+
See the LICENSE file in the project root for the full license text.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
__version__ = "0.0.1"
|
|
18
|
+
|
|
19
|
+
from .translator import DSLTranslator, Entity
|
docdsl/commands.py
ADDED
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
"""
|
|
2
|
+
File: commands.py
|
|
3
|
+
Project: Docdsl
|
|
4
|
+
File Created: Wed 15 Jul 2026 08:07:54 (Shine Jayakumar)
|
|
5
|
+
Author: Shine Jayakumar (shinejayakumar@yahoo.com)
|
|
6
|
+
-----
|
|
7
|
+
Last Modified: Wed 15 Jul 2026 08:07:54 (Shine Jayakumar)
|
|
8
|
+
Modified By: Shine Jayakumar (shinejayakumar@yahoo.com)
|
|
9
|
+
-----
|
|
10
|
+
Copyright (c) 2026 Shine Jayakumar
|
|
11
|
+
SPDX-License-Identifier: MIT
|
|
12
|
+
|
|
13
|
+
Licensed under the MIT License.
|
|
14
|
+
See the LICENSE file in the project root for the full license text.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import re
|
|
18
|
+
from dataclasses import dataclass, field
|
|
19
|
+
from .dsl_builtins import *
|
|
20
|
+
from .text_to_regex import TextToRegex
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass
|
|
24
|
+
class Entity:
|
|
25
|
+
parent: object
|
|
26
|
+
name: str
|
|
27
|
+
|
|
28
|
+
@property
|
|
29
|
+
def group_name(self):
|
|
30
|
+
return f"{self.name[1:]}"
|
|
31
|
+
|
|
32
|
+
def to_regex(self):
|
|
33
|
+
return f"__{self.name[1:]}__"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@dataclass
|
|
37
|
+
class Command:
|
|
38
|
+
parent: object
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@dataclass
|
|
42
|
+
class Find(Command):
|
|
43
|
+
items: list = None
|
|
44
|
+
|
|
45
|
+
def to_regex(self):
|
|
46
|
+
pat_parts = [item.to_regex() for item in self.items]
|
|
47
|
+
pattern = "|".join(pat_parts)
|
|
48
|
+
pattern = f"(?:{pattern})" if len(self.items) > 1 else pattern
|
|
49
|
+
return pattern
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@dataclass
|
|
53
|
+
class FindItem(Command):
|
|
54
|
+
|
|
55
|
+
text: str = ""
|
|
56
|
+
ignorecase: bool = False
|
|
57
|
+
|
|
58
|
+
def to_regex(self):
|
|
59
|
+
pat = TextToRegex().get_regex(self.text)
|
|
60
|
+
pat = f"(?i:{pat})" if self.ignorecase else pat
|
|
61
|
+
return pat
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@dataclass
|
|
65
|
+
class Skip(Command):
|
|
66
|
+
|
|
67
|
+
position: str = ""
|
|
68
|
+
until: str = ""
|
|
69
|
+
ignorecase: bool = False
|
|
70
|
+
|
|
71
|
+
def to_regex(self):
|
|
72
|
+
if self.position:
|
|
73
|
+
return self.position.to_regex()
|
|
74
|
+
|
|
75
|
+
if self.until:
|
|
76
|
+
until = re.escape(self.until)
|
|
77
|
+
until = f"(?i:{until})" if self.ignorecase else until
|
|
78
|
+
pat = rf".*?{until}"
|
|
79
|
+
return pat
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@dataclass
|
|
83
|
+
class SkipLines(Command):
|
|
84
|
+
|
|
85
|
+
until: str
|
|
86
|
+
|
|
87
|
+
def to_regex(self):
|
|
88
|
+
until = re.escape(self.until)
|
|
89
|
+
pat = rf"[\s\S]*?{until}"
|
|
90
|
+
return pat
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@dataclass
|
|
94
|
+
class SkipNLines(Command):
|
|
95
|
+
|
|
96
|
+
lines: int
|
|
97
|
+
|
|
98
|
+
def to_regex(self):
|
|
99
|
+
pat = rf"(?:.*[\r\n]){{{self.lines}}}"
|
|
100
|
+
return pat
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
#@dataclass
|
|
104
|
+
#class Capture(Command):
|
|
105
|
+
#
|
|
106
|
+
# items: list = None
|
|
107
|
+
# until: str = ""
|
|
108
|
+
# position: Position = None
|
|
109
|
+
#
|
|
110
|
+
# def to_regex(self):
|
|
111
|
+
# target_count = sum([bool(item.target) for item in self.items])
|
|
112
|
+
# if not target_count:
|
|
113
|
+
# raise Exception("CAPTURE requires at least one target entity")
|
|
114
|
+
# if target_count > 1:
|
|
115
|
+
# raise Exception("CAPTURE cannot have more than one target entity")
|
|
116
|
+
#
|
|
117
|
+
# target = self.items[-1]
|
|
118
|
+
# pat_parts = [item.to_regex() for item in self.items[:-1]]
|
|
119
|
+
# target_pat = target.target.to_regex()
|
|
120
|
+
# group_name = target.target.entity.group_name
|
|
121
|
+
# pat_parts.append(f"(?P<{group_name}>{target_pat})")
|
|
122
|
+
# if self.until:
|
|
123
|
+
# until_pat = TextToRegex().get_regex(self.until)
|
|
124
|
+
# pat_parts.append(until_pat)
|
|
125
|
+
# elif self.position:
|
|
126
|
+
# pos = self.position.to_regex()
|
|
127
|
+
# pat_parts.append(pos)
|
|
128
|
+
# return "".join(pat_parts)
|
|
129
|
+
|
|
130
|
+
#def __repr__(self):
|
|
131
|
+
# return (
|
|
132
|
+
# "Capture(items=[\n"
|
|
133
|
+
# f"{self.items}\n]\n,"
|
|
134
|
+
# f"until={self.until},\n"
|
|
135
|
+
# f"position={self.position}\n"
|
|
136
|
+
# ")"
|
|
137
|
+
# )
|
|
138
|
+
@dataclass
|
|
139
|
+
class TargetEntity(Command):
|
|
140
|
+
|
|
141
|
+
entity: Entity
|
|
142
|
+
|
|
143
|
+
def to_regex(self):
|
|
144
|
+
return self.entity.to_regex()
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
@dataclass
|
|
149
|
+
class Capture(Command):
|
|
150
|
+
|
|
151
|
+
items: list = None
|
|
152
|
+
target: TargetEntity = None
|
|
153
|
+
until: str = ""
|
|
154
|
+
position: Position = None
|
|
155
|
+
|
|
156
|
+
def to_regex(self):
|
|
157
|
+
pat_parts = [item.to_regex() for item in self.items]
|
|
158
|
+
target_pat = self.target.entity.to_regex()
|
|
159
|
+
group_name = self.target.entity.group_name
|
|
160
|
+
pat_parts.append(f"(?P<{group_name}>{target_pat})")
|
|
161
|
+
if self.until:
|
|
162
|
+
until_pat = TextToRegex().get_regex(self.until)
|
|
163
|
+
pat_parts.append(until_pat)
|
|
164
|
+
elif self.position:
|
|
165
|
+
pos = self.position.to_regex()
|
|
166
|
+
pat_parts.append(pos)
|
|
167
|
+
return "".join(pat_parts)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
#@dataclass
|
|
172
|
+
#class CaptureItem(Command):
|
|
173
|
+
#
|
|
174
|
+
# optional: bool = False
|
|
175
|
+
# builtin: Builtin=None
|
|
176
|
+
# entity: str = None
|
|
177
|
+
# target: TargetEntity = None
|
|
178
|
+
#
|
|
179
|
+
# def to_regex(self):
|
|
180
|
+
# if self.builtin:
|
|
181
|
+
# pat = self.builtin.to_regex()
|
|
182
|
+
# pat = f"{pat}?" if self.optional else pat
|
|
183
|
+
# return pat
|
|
184
|
+
#
|
|
185
|
+
# if self.entity:
|
|
186
|
+
# pat = self.entity.to_regex()
|
|
187
|
+
# pat = f"{pat}?" if self.optional else pat
|
|
188
|
+
# return pat
|
|
189
|
+
#
|
|
190
|
+
# if self.target:
|
|
191
|
+
# return self.target.entity.to_regex()
|
|
192
|
+
|
|
193
|
+
@dataclass
|
|
194
|
+
class CaptureItem(Command):
|
|
195
|
+
|
|
196
|
+
optional: bool = False
|
|
197
|
+
builtin: Builtin=None
|
|
198
|
+
entity: str = None
|
|
199
|
+
|
|
200
|
+
def to_regex(self):
|
|
201
|
+
if self.builtin:
|
|
202
|
+
pat = self.builtin.to_regex()
|
|
203
|
+
pat = f"{pat}?" if self.optional else pat
|
|
204
|
+
return pat
|
|
205
|
+
|
|
206
|
+
if self.entity:
|
|
207
|
+
pat = self.entity.to_regex()
|
|
208
|
+
pat = f"{pat}?" if self.optional else pat
|
|
209
|
+
return pat
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
@dataclass
|
|
213
|
+
class CaptureNLines(Command):
|
|
214
|
+
|
|
215
|
+
lines: int
|
|
216
|
+
target: TargetEntity
|
|
217
|
+
|
|
218
|
+
def to_regex(self):
|
|
219
|
+
group_name = self.target.entity.group_name
|
|
220
|
+
#pat = rf"(?P<{entity}>(?:.*[\r\n]){{{self.lines}}})"
|
|
221
|
+
pat = rf"(?P<{group_name}>(?:.*\r?\n){{{self.lines}}})"
|
|
222
|
+
return pat
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
@dataclass
|
|
226
|
+
class CaptureLines(Command):
|
|
227
|
+
|
|
228
|
+
until: str
|
|
229
|
+
target: TargetEntity
|
|
230
|
+
ignorecase: bool = False
|
|
231
|
+
|
|
232
|
+
def to_regex(self):
|
|
233
|
+
group_name = self.target.entity.group_name
|
|
234
|
+
between = AcrossLines(None, None).to_regex()
|
|
235
|
+
until = TextToRegex().get_regex(self.until)
|
|
236
|
+
until = f"(?i:{until})" if self.ignorecase else until
|
|
237
|
+
pat = rf"(?P<{group_name}>{between}){until}"
|
|
238
|
+
return pat
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
@dataclass
|
|
242
|
+
class CaptureBetween(Command):
|
|
243
|
+
|
|
244
|
+
start: str
|
|
245
|
+
end: str
|
|
246
|
+
target: TargetEntity
|
|
247
|
+
scope: CaptureLinesScope = None
|
|
248
|
+
|
|
249
|
+
def to_regex(self):
|
|
250
|
+
group_name = self.target.entity.group_name
|
|
251
|
+
start = self.start.to_regex()
|
|
252
|
+
end = self.end.to_regex()
|
|
253
|
+
between = (
|
|
254
|
+
AcrossLines(None, None).to_regex() if not self.scope
|
|
255
|
+
else self.scope.to_regex()
|
|
256
|
+
)
|
|
257
|
+
pat = rf"{start}(?P<{group_name}>{between}){end}"
|
|
258
|
+
return pat
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
@dataclass
|
|
262
|
+
class CaptureBetweenItem(Command):
|
|
263
|
+
|
|
264
|
+
text: str
|
|
265
|
+
ignorecase: bool = False
|
|
266
|
+
|
|
267
|
+
def to_regex(self):
|
|
268
|
+
pat = TextToRegex().get_regex(self.text)
|
|
269
|
+
pat = f"(?i:{pat})" if self.ignorecase else pat
|
|
270
|
+
return pat
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
@dataclass
|
|
274
|
+
class If(Command):
|
|
275
|
+
|
|
276
|
+
items: list = None
|
|
277
|
+
commands: list[Command] = None
|
|
278
|
+
|
|
279
|
+
def _get_item_pattern(self) -> str:
|
|
280
|
+
pat_parts = [item.to_regex() for item in self.items]
|
|
281
|
+
pat = "|".join(pat_parts)
|
|
282
|
+
pat = f"({pat})" if len(pat_parts) > 1 else pat
|
|
283
|
+
return pat
|
|
284
|
+
|
|
285
|
+
def _get_command_pattern(self) -> str:
|
|
286
|
+
pat_parts = [cmd.to_regex() for cmd in self.commands]
|
|
287
|
+
pat = "".join(pat_parts)
|
|
288
|
+
return pat
|
|
289
|
+
|
|
290
|
+
def to_regex(self):
|
|
291
|
+
#pat_parts = [item.to_regex() for item in self.items]
|
|
292
|
+
#pat = "|".join(pat_parts)
|
|
293
|
+
#pat = f"({pat})" if len(pat_parts) > 1 else pat
|
|
294
|
+
|
|
295
|
+
#pat += self.action.to_regex()
|
|
296
|
+
pat = self._get_item_pattern()
|
|
297
|
+
pat += self._get_command_pattern()
|
|
298
|
+
pat = f"(?:{pat})?"
|
|
299
|
+
return pat
|
|
300
|
+
|
|
301
|
+
#for item in self.items:
|
|
302
|
+
# pat = self.item.to_regex()
|
|
303
|
+
#pat = ""
|
|
304
|
+
#if self.keyword:
|
|
305
|
+
# kwd_pattern = TextToRegex().get_regex(self.keyword)
|
|
306
|
+
# pat += kwd_pattern
|
|
307
|
+
#elif self.entity:
|
|
308
|
+
# ent = f"__{self.entity}__"
|
|
309
|
+
# pat += ent
|
|
310
|
+
#action_pattern = self.action.to_regex()
|
|
311
|
+
#pat += action_pattern
|
|
312
|
+
#pat = f"(?:{pat})?"
|
|
313
|
+
#return pat
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
@dataclass
|
|
318
|
+
class IfItem(Command):
|
|
319
|
+
|
|
320
|
+
text: str = ""
|
|
321
|
+
entity: Entity = None
|
|
322
|
+
ignorecase: bool = False
|
|
323
|
+
|
|
324
|
+
def to_regex(self):
|
|
325
|
+
if self.text:
|
|
326
|
+
pat = TextToRegex().get_regex(self.text)
|
|
327
|
+
pat = f"(?i:{pat})" if self.ignorecase else pat
|
|
328
|
+
return pat
|
|
329
|
+
|
|
330
|
+
# for entity
|
|
331
|
+
pat = self.entity.to_regex()
|
|
332
|
+
pat = f"(?i:{pat})" if self.ignorecase else pat
|
|
333
|
+
return pat
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
if __name__ == "__main__":
|
|
338
|
+
pass
|
docdsl/dsl_builtins.py
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"""
|
|
2
|
+
File: dsl_builtins.py
|
|
3
|
+
Project: Docdsl
|
|
4
|
+
File Created: Wed 15 Jul 2026 08:08:02 (Shine Jayakumar)
|
|
5
|
+
Author: Shine Jayakumar (shinejayakumar@yahoo.com)
|
|
6
|
+
-----
|
|
7
|
+
Last Modified: Wed 15 Jul 2026 08:08:02 (Shine Jayakumar)
|
|
8
|
+
Modified By: Shine Jayakumar (shinejayakumar@yahoo.com)
|
|
9
|
+
-----
|
|
10
|
+
Copyright (c) 2026 Shine Jayakumar
|
|
11
|
+
SPDX-License-Identifier: MIT
|
|
12
|
+
|
|
13
|
+
Licensed under the MIT License.
|
|
14
|
+
See the LICENSE file in the project root for the full license text.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from abc import ABC, abstractmethod
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class Position(ABC):
|
|
21
|
+
|
|
22
|
+
def __init__(self, parent, value):
|
|
23
|
+
self.value = value
|
|
24
|
+
|
|
25
|
+
@abstractmethod
|
|
26
|
+
def to_regex(self):
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
class End(Position):
|
|
30
|
+
|
|
31
|
+
def to_regex(self):
|
|
32
|
+
return r"[^\r\n]*"
|
|
33
|
+
|
|
34
|
+
def __repr__(self):
|
|
35
|
+
return f"End(value='{self.value}')"
|
|
36
|
+
|
|
37
|
+
class NewLine(Position):
|
|
38
|
+
|
|
39
|
+
def to_regex(self):
|
|
40
|
+
return r"[^\r\n]*\s*"
|
|
41
|
+
|
|
42
|
+
def __repr__(self):
|
|
43
|
+
return f"NewLine(value='{self.value}')"
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class Builtin(ABC):
|
|
47
|
+
|
|
48
|
+
def __init__(self, parent, value):
|
|
49
|
+
self.value = value
|
|
50
|
+
|
|
51
|
+
@abstractmethod
|
|
52
|
+
def to_regex(self):
|
|
53
|
+
pass
|
|
54
|
+
|
|
55
|
+
class Spaces(Builtin):
|
|
56
|
+
|
|
57
|
+
def to_regex(self):
|
|
58
|
+
return r"(?:[ \t]+)"
|
|
59
|
+
|
|
60
|
+
def __repr__(self):
|
|
61
|
+
return f"Spaces(value='{self.value}')"
|
|
62
|
+
|
|
63
|
+
class WhiteSpaces(Builtin):
|
|
64
|
+
|
|
65
|
+
def to_regex(self):
|
|
66
|
+
return r"(?:\s+)"
|
|
67
|
+
|
|
68
|
+
def __repr__(self):
|
|
69
|
+
return f"WhiteSpaces(value='{self.value}')"
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class Digits(Builtin):
|
|
73
|
+
|
|
74
|
+
def to_regex(self):
|
|
75
|
+
return r"(?:\d+)"
|
|
76
|
+
|
|
77
|
+
def __repr__(self):
|
|
78
|
+
return f"Digits(value='{self.value}')"
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class AlphaNums(Builtin):
|
|
82
|
+
|
|
83
|
+
def to_regex(self):
|
|
84
|
+
return "(?:[A-Za-z\d]+)"
|
|
85
|
+
|
|
86
|
+
def __repr__(self):
|
|
87
|
+
return f"AlphaNums(value='{self.value}')"
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class CaptureLinesScope(ABC):
|
|
91
|
+
|
|
92
|
+
def __init__(self, parent, value):
|
|
93
|
+
self.value = value
|
|
94
|
+
|
|
95
|
+
@abstractmethod
|
|
96
|
+
def to_regex(self):
|
|
97
|
+
pass
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class SameLine(CaptureLinesScope):
|
|
101
|
+
|
|
102
|
+
def to_regex(self):
|
|
103
|
+
return r"(?:.*?)"
|
|
104
|
+
|
|
105
|
+
def __repr__(self):
|
|
106
|
+
return f"SameLine(value='{self.value}')"
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class AcrossLines(CaptureLinesScope):
|
|
110
|
+
|
|
111
|
+
def to_regex(self):
|
|
112
|
+
return r"(?s:.*?)"
|
|
113
|
+
|
|
114
|
+
def __repr__(self):
|
|
115
|
+
return f"AcrossLines(value='{self.value}')"
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
if __name__ == "__main__":
|
|
119
|
+
pass
|
docdsl/dtformats.py
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
"""
|
|
2
|
+
File: dtformats.py
|
|
3
|
+
Project: Docdsl
|
|
4
|
+
File Created: Wed 15 Jul 2026 08:08:21 (Shine Jayakumar)
|
|
5
|
+
Author: Shine Jayakumar (shinejayakumar@yahoo.com)
|
|
6
|
+
-----
|
|
7
|
+
Last Modified: Wed 15 Jul 2026 08:08:21 (Shine Jayakumar)
|
|
8
|
+
Modified By: Shine Jayakumar (shinejayakumar@yahoo.com)
|
|
9
|
+
-----
|
|
10
|
+
Copyright (c) 2026 Shine Jayakumar
|
|
11
|
+
SPDX-License-Identifier: MIT
|
|
12
|
+
|
|
13
|
+
Licensed under the MIT License.
|
|
14
|
+
See the LICENSE file in the project root for the full license text.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import re
|
|
18
|
+
|
|
19
|
+
WEEKDAYS_FULL = ('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday')
|
|
20
|
+
WEEKDAYS_ABBR = ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')
|
|
21
|
+
MONTHS_FULL = ('January', 'February', 'March','April', 'May','June',
|
|
22
|
+
'July','August','September' ,'October','November','December')
|
|
23
|
+
MONTHS_ABBR = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
|
|
24
|
+
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def get_dtformat_suffixed(dtstr: str):
|
|
28
|
+
""" Returns date formats for dates with suffixes (st, nd, rd, th) """
|
|
29
|
+
dtstr = re.sub(r'\s+', ' ', dtstr.strip())
|
|
30
|
+
dtstr = re.sub(f'({"|".join(WEEKDAYS_FULL)})', '%A', dtstr) # Monday
|
|
31
|
+
dtstr = re.sub(f'({"|".join(WEEKDAYS_ABBR)})', '%a', dtstr) # Mon
|
|
32
|
+
dtstr = re.sub(f'({"|".join(MONTHS_FULL)})', '%B', dtstr) # January
|
|
33
|
+
dtstr = re.sub(f'({"|".join(MONTHS_ABBR)})', '%b', dtstr) # Jan
|
|
34
|
+
dtstr = re.sub(r'^(\d{1,2})(st|nd|rd|th)', r'%d\2', dtstr)
|
|
35
|
+
dtstr = re.sub(r'\s+(\d{1,2})(st|nd|rd|th)', r' %d\2', dtstr)
|
|
36
|
+
dtstr = re.sub(r'\d{4}', '%Y', dtstr)
|
|
37
|
+
dtstr = re.sub(r'\d{2}', '%y', dtstr)
|
|
38
|
+
|
|
39
|
+
patterns = []
|
|
40
|
+
patterns.append(re.sub(r'(st|nd|rd|th)', 'st', dtstr))
|
|
41
|
+
patterns.append(re.sub(r'(st|nd|rd|th)', 'nd', dtstr))
|
|
42
|
+
patterns.append(re.sub(r'(st|nd|rd|th)', 'rd', dtstr))
|
|
43
|
+
patterns.append(re.sub(r'(st|nd|rd|th)', 'th', dtstr))
|
|
44
|
+
|
|
45
|
+
return patterns
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
DTSAMPLE_PYFORMAT_MAP = {
|
|
49
|
+
"02 March 1999": "%d %B %Y",
|
|
50
|
+
"02-March-1999": "%d-%B-%Y",
|
|
51
|
+
"02/March/1999": "%d/%B/%Y",
|
|
52
|
+
"02.March.1999": "%d.%B.%Y",
|
|
53
|
+
|
|
54
|
+
"02 March 99": "%d %B %y",
|
|
55
|
+
"02-March-99": "%d-%B-%y",
|
|
56
|
+
"02/March/99": "%d/%B/%y",
|
|
57
|
+
"02.March.99": "%d.%B.%y",
|
|
58
|
+
|
|
59
|
+
"02 Mar 1999": "%d %b %Y",
|
|
60
|
+
"02-Mar-1999": "%d-%b-%Y",
|
|
61
|
+
"02/Mar/1999": "%d/%b/%Y",
|
|
62
|
+
"02.Mar.1999": "%d.%b.%Y",
|
|
63
|
+
|
|
64
|
+
"02 Mar 99": "%d %b %y",
|
|
65
|
+
"02-Mar-99": "%d-%b-%y",
|
|
66
|
+
"02/Mar/99": "%d/%b/%y",
|
|
67
|
+
"02.Mar.99": "%d.%b.%y",
|
|
68
|
+
|
|
69
|
+
"Mar 02 1999": "%b %d %Y",
|
|
70
|
+
"Mar-02-1999": "%b-%d-%Y",
|
|
71
|
+
"Mar/02/1999": "%b/%d/%Y",
|
|
72
|
+
"Mar.02.1999": "%b.%d.%Y",
|
|
73
|
+
|
|
74
|
+
"Mar 02 99": "%b %d %y",
|
|
75
|
+
"Mar-02-99": "%b-%d-%y",
|
|
76
|
+
"Mar/02/99": "%b/%d/%y",
|
|
77
|
+
"Mar.02.99": "%b.%d.%y",
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
"March 02 1999": "%B %d %Y",
|
|
81
|
+
"March-02-1999": "%B-%d-%Y",
|
|
82
|
+
"March/02/1999": "%B/%d/%Y",
|
|
83
|
+
"March.02.1999": "%B.%d.%Y",
|
|
84
|
+
|
|
85
|
+
"March 02 99": "%B %d %y",
|
|
86
|
+
"March-02-99": "%B-%d-%y",
|
|
87
|
+
"March/02/99": "%B/%d/%y",
|
|
88
|
+
"March.02.99": "%B.%d.%y",
|
|
89
|
+
|
|
90
|
+
"Monday, 02 March 1999": "%A, %d %B %Y",
|
|
91
|
+
"Monday, 02 Mar 1999": "%A, %d %b %Y",
|
|
92
|
+
|
|
93
|
+
"Mon, 02 March 1999": "%a, %d %B %Y",
|
|
94
|
+
"Mon, 02 Mar 1999": "%a, %d %b %Y",
|
|
95
|
+
|
|
96
|
+
"Monday, March 02, 1999": "%A, %B %d, %Y",
|
|
97
|
+
"Monday, March 02 1999": "%A, %B %d %Y",
|
|
98
|
+
|
|
99
|
+
"Monday, Mar 02, 1999": "%A, %b %d, %Y",
|
|
100
|
+
"Monday, Mar 02 1999": "%A, %b %d %Y",
|
|
101
|
+
|
|
102
|
+
"Mon, March 02, 1999": "%a, %B %d, %Y",
|
|
103
|
+
"Mon, March 02 1999": "%a, %B %d %Y",
|
|
104
|
+
|
|
105
|
+
"Mon, Mar 02, 1999": "%a, %b %d, %Y",
|
|
106
|
+
"Mon, Mar 02 1999": "%a, %b %d %Y",
|
|
107
|
+
|
|
108
|
+
"Monday, 02 March 99": "%A, %d %B %y",
|
|
109
|
+
"Monday, 02 Mar 99": "%A, %d %b %y",
|
|
110
|
+
|
|
111
|
+
"Mon, 02 March 99": "%a, %d %B %y",
|
|
112
|
+
"Mon, 02 Mar 99": "%a, %d %b %y",
|
|
113
|
+
|
|
114
|
+
"Monday, March 02, 99": "%A, %B %d, %y",
|
|
115
|
+
"Monday, March 02 99": "%A, %B %d %y",
|
|
116
|
+
|
|
117
|
+
"Monday, Mar 02, 99": "%A, %b %d, %y",
|
|
118
|
+
"Monday, Mar 02 99": "%A, %b %d %y",
|
|
119
|
+
|
|
120
|
+
"Mon, March 02, 99": "%a, %B %d, %y",
|
|
121
|
+
"Mon, March 02 99": "%a, %B %d %y",
|
|
122
|
+
|
|
123
|
+
"Mon, Mar 02, 99": "%a, %b %d, %y",
|
|
124
|
+
"Mon, Mar 02 99": "%a, %b %d %y",
|
|
125
|
+
|
|
126
|
+
"Monday 2nd March 1999": ('%A %dst %B %Y', '%A %dnd %B %Y', '%A %drd %B %Y', '%A %dth %B %Y'),
|
|
127
|
+
"Monday 2nd Mar 1999": ('%A %dst %b %Y', '%A %dnd %b %Y', '%A %drd %b %Y', '%A %dth %b %Y'),
|
|
128
|
+
"Monday 2nd March 99": ('%A %dst %B %y', '%A %dnd %B %y', '%A %drd %B %y', '%A %dth %B %y'),
|
|
129
|
+
"Monday 2nd Mar 99": ('%A %dst %b %y', '%A %dnd %b %y', '%A %drd %b %y', '%A %dth %b %y'),
|
|
130
|
+
|
|
131
|
+
"Mon 2nd March 1999": ('%a %dst %B %Y', '%a %dnd %B %Y', '%a %drd %B %Y', '%a %dth %B %Y'),
|
|
132
|
+
"Mon 2nd Mar 1999": ('%a %dst %b %Y', '%a %dnd %b %Y', '%a %drd %b %Y', '%a %dth %b %Y'),
|
|
133
|
+
"Mon 2nd March 99": ('%a %dst %B %y', '%a %dnd %B %y', '%a %drd %B %y', '%a %dth %B %y'),
|
|
134
|
+
"Mon 2nd Mar 99": ('%a %dst %b %y', '%a %dnd %b %y', '%a %drd %b %y', '%a %dth %b %y'),
|
|
135
|
+
|
|
136
|
+
"Monday, 2nd March 1999": ('%A, %dst %B %Y', '%A %dnd %B %Y', '%A %drd %B %Y', '%A %dth %B %Y'),
|
|
137
|
+
"Monday, 2nd Mar 1999": ('%A, %dst %b %Y', '%A %dnd %b %Y', '%A %drd %b %Y', '%A %dth %b %Y'),
|
|
138
|
+
"Monday, 2nd March 99": ('%A, %dst %B %y', '%A %dnd %B %y', '%A %drd %B %y', '%A %dth %B %y'),
|
|
139
|
+
"Monday, 2nd Mar 99": ('%A, %dst %b %y', '%A %dnd %b %y', '%A %drd %b %y', '%A %dth %b %y'),
|
|
140
|
+
|
|
141
|
+
"Mon, 2nd March 1999": ('%a, %dst %B %Y', '%a %dnd %B %Y', '%a %drd %B %Y', '%a %dth %B %Y'),
|
|
142
|
+
"Mon, 2nd Mar 1999": ('%a, %dst %b %Y', '%a %dnd %b %Y', '%a %drd %b %Y', '%a %dth %b %Y'),
|
|
143
|
+
"Mon, 2nd March 99": ('%a, %dst %B %y', '%a %dnd %B %y', '%a %drd %B %y', '%a %dth %B %y'),
|
|
144
|
+
"Mon, 2nd Mar 99": ('%a, %dst %b %y', '%a %dnd %b %y', '%a %drd %b %y', '%a %dth %b %y'),
|
|
145
|
+
|
|
146
|
+
"2nd March 1999": ('%dst %B %Y', '%dnd %B %Y', '%drd %B %Y', '%dth %B %Y'),
|
|
147
|
+
"2nd March 99": ('%dst %B %y', '%dnd %B %y', '%drd %B %y', '%dth %B %y'),
|
|
148
|
+
|
|
149
|
+
"2nd Mar 1999": ('%dst %b %Y', '%dnd %b %Y', '%drd %b %Y', '%dth %b %Y'),
|
|
150
|
+
"2nd Mar 99": ('%dst %b %y', '%dnd %b %y', '%drd %b %y', '%dth %b %y'),
|
|
151
|
+
|
|
152
|
+
# yyyy mm dd
|
|
153
|
+
"1999-02-22": "%Y-%m-%d",
|
|
154
|
+
"1999/02/22": "%Y/%m/%d",
|
|
155
|
+
"1999.02.22": "%Y.%m.%d",
|
|
156
|
+
"1999 02 22": "%Y %m %d",
|
|
157
|
+
|
|
158
|
+
# yy mm dd
|
|
159
|
+
"99-02-22": "%y-%m-%d",
|
|
160
|
+
"99/02/22": "%y/%m/%d",
|
|
161
|
+
"99.02.22": "%y.%m.%d",
|
|
162
|
+
"99 02 22": "%y %m %d",
|
|
163
|
+
|
|
164
|
+
# mm dd yy
|
|
165
|
+
"02/22/99": "%m/%d/%y",
|
|
166
|
+
"02-22-99": "%m-%d-%y",
|
|
167
|
+
"02.22.99": "%m.%d.%y",
|
|
168
|
+
"02 22 99": "%m %d %y",
|
|
169
|
+
|
|
170
|
+
# mm dd yyyy
|
|
171
|
+
"02/22/1999": "%m/%d/%Y",
|
|
172
|
+
"02-22-1999": "%m-%d-%Y",
|
|
173
|
+
"02.22.1999": "%m.%d.%Y",
|
|
174
|
+
"02 22 1999": "%m %d %Y",
|
|
175
|
+
|
|
176
|
+
# dd mm yy
|
|
177
|
+
"22/02/99": "%d/%m/%y",
|
|
178
|
+
"22-02-99": "%d-%m-%y",
|
|
179
|
+
"22.02.99": "%d.%m.%y",
|
|
180
|
+
"22 02 99": "%d %m %y",
|
|
181
|
+
|
|
182
|
+
# dd mm yyyy
|
|
183
|
+
"22/02/1999": "%d/%m/%Y",
|
|
184
|
+
"22-02-1999": "%d-%m-%Y",
|
|
185
|
+
"22.02.1999": "%d.%m.%Y",
|
|
186
|
+
"22 02 1999": "%d %m %Y",
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if __name__ == '__main__':
|
|
190
|
+
pass
|