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 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