|
2 | 2 | # Handles the transformation logic for each field based on the schema |
3 | 3 | # Root and base type expression checker functions |
4 | 4 | import ExceptionMessages |
5 | | -from datetime import datetime,timezone |
| 5 | +from datetime import datetime,timedelta, timezone |
6 | 6 | from zoneinfo import ZoneInfo |
7 | 7 | import re |
8 | 8 | from LookUpData import LookUpData |
@@ -136,40 +136,36 @@ def _convertToDateTime(self, expressionRule, fieldName, fieldValue, summarise, r |
136 | 136 | if not fieldValue: |
137 | 137 | return "" |
138 | 138 |
|
139 | | - # Reject partial dates like "2024" or "2024-05" |
140 | | - if re.match(r"^\d{4}(-\d{2})?$", fieldValue): |
141 | | - raise RecordError( |
142 | | - ExceptionMessages.RECORD_CHECK_FAILED, |
143 | | - f"{fieldName} rejected: partial datetime not accepted.", |
144 | | - f"Invalid partial datetime: {fieldValue}", |
145 | | - ) |
146 | 139 | try: |
147 | | - dt = datetime.fromisoformat(fieldValue) |
148 | | - except ValueError: |
| 140 | + if not expressionRule: |
| 141 | + # Handle YYYYMMDD format to |
| 142 | + dt = datetime.strptime(fieldValue, "%Y%m%d") |
| 143 | + dt = dt.replace(hour=0, minute=0, second=0) |
| 144 | + else: |
| 145 | + dt = datetime.fromisoformat(fieldValue) |
| 146 | + if dt.tzinfo is None: |
| 147 | + dt = dt.replace(tzinfo=timezone.utc) |
| 148 | + except Exception as e: |
149 | 149 | if report_unexpected_exception: |
150 | | - return f"Unexpected format: {fieldValue}" |
| 150 | + self._log_error(fieldName, fieldValue, e) |
| 151 | + return "" |
151 | 152 |
|
152 | 153 | # Allow only +00:00 or +01:00 offsets (UTC and BST) and reject unsupported timezones |
153 | 154 | offset = dt.utcoffset() |
154 | | - allowed_offsets = [ZoneInfo("UTC").utcoffset(dt), |
155 | | - ZoneInfo("Europe/London").utcoffset(dt)] |
156 | | - if offset not in allowed_offsets: |
157 | | - raise RecordError( |
158 | | - ExceptionMessages.RECORD_CHECK_FAILED, |
159 | | - f"{fieldName} rejected: unsupported timezone.", |
160 | | - f"Unsupported offset: {offset}", |
161 | | - ) |
| 155 | + allowed_offsets = [timedelta(hours=0), timedelta(hours=1)] |
| 156 | + if offset is not None and offset not in allowed_offsets: |
| 157 | + if report_unexpected_exception: |
| 158 | + self._log_error(fieldName, fieldValue, "Unsupported Format or offset") |
| 159 | + return "" |
162 | 160 |
|
163 | 161 | # Convert to UTC |
164 | | - dt_utc = dt.astimezone(ZoneInfo("UTC")).replace(microsecond=0) |
165 | | - |
166 | | - format_str = expressionRule.replace("format:", "") |
| 162 | + dt_utc = dt.replace(microsecond=0) |
167 | 163 |
|
168 | | - if format_str == "csv-utc": |
| 164 | + if expressionRule == "csv-utc": |
169 | 165 | formatted = dt_utc.strftime("%Y%m%dT%H%M%S%z") |
170 | 166 | return formatted.replace("+0000", "00").replace("+0100", "01") |
171 | 167 |
|
172 | | - return dt_utc.strftime(format_str) |
| 168 | + return dt_utc.strftime("%Y%m%dT%H%M%S%z") |
173 | 169 |
|
174 | 170 | # Not Empty Validate - Returns exactly what is in the extracted fields no parsing or logic needed |
175 | 171 | def _convertToNotEmpty(self, expressionRule, fieldName, fieldValue, summarise, report_unexpected_exception): |
|
0 commit comments