mirror of https://gitlab.com/pamhyr/pamhyr2
Time/Date: accept different formats for date, YYYY-MM-DD [HH:MM[:SS]], DD-MM-YYYY [HH:MM[:SS]] and DD/MM/YYYY [HH:MM[:SS]], convert it to classic one used by pamhyr, and prevent user when he's using a wrong one
parent
6586a7b191
commit
0f1d1b0797
|
|
@ -24,7 +24,7 @@ from datetime import date, time, datetime, timedelta
|
|||
from tools import (
|
||||
trace, timer,
|
||||
timestamp_to_old_pamhyr_date,
|
||||
old_pamhyr_date_to_timestamp
|
||||
old_pamhyr_date_to_timestamp, format_datetime
|
||||
)
|
||||
|
||||
from View.Tools.PamhyrTable import PamhyrTableModel
|
||||
|
|
@ -97,7 +97,7 @@ class TableModel(PamhyrTableModel):
|
|||
if self._opt_data == "time":
|
||||
value = timestamp_to_old_pamhyr_date(int(v))
|
||||
else:
|
||||
value = str(
|
||||
value = format_datetime(
|
||||
self._start_date + timedelta(seconds=float(v))
|
||||
)
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ from datetime import date, time, datetime, timedelta
|
|||
from tools import (
|
||||
trace, timer,
|
||||
timestamp_to_old_pamhyr_date,
|
||||
old_pamhyr_date_to_timestamp
|
||||
old_pamhyr_date_to_timestamp, format_datetime
|
||||
)
|
||||
|
||||
from View.Tools.PamhyrTable import PamhyrTableModel
|
||||
|
|
@ -87,7 +87,7 @@ class TableModel(PamhyrTableModel):
|
|||
if self._opt_data == "time":
|
||||
value = timestamp_to_old_pamhyr_date(int(v))
|
||||
else:
|
||||
value = str(
|
||||
value = format_datetime(
|
||||
self._start_date + timedelta(seconds=float(v))
|
||||
)
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ from datetime import date, time, datetime, timedelta
|
|||
from tools import (
|
||||
trace, timer,
|
||||
timestamp_to_old_pamhyr_date,
|
||||
old_pamhyr_date_to_timestamp
|
||||
old_pamhyr_date_to_timestamp, format_datetime
|
||||
)
|
||||
|
||||
from View.Tools.PamhyrTable import PamhyrTableModel
|
||||
|
|
@ -87,7 +87,7 @@ class TableModel(PamhyrTableModel):
|
|||
if self._opt_data == "time":
|
||||
value = timestamp_to_old_pamhyr_date(int(v))
|
||||
else:
|
||||
value = str(
|
||||
value = format_datetime(
|
||||
self._start_date + timedelta(seconds=float(v))
|
||||
)
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ from datetime import date, time, datetime, timedelta
|
|||
from tools import (
|
||||
trace, timer,
|
||||
timestamp_to_old_pamhyr_date,
|
||||
old_pamhyr_date_to_timestamp
|
||||
old_pamhyr_date_to_timestamp, format_datetime
|
||||
)
|
||||
|
||||
from View.Tools.PamhyrTable import PamhyrTableModel
|
||||
|
|
@ -76,7 +76,7 @@ class TableModel(PamhyrTableModel):
|
|||
if self._opt_data == "time":
|
||||
value = timestamp_to_old_pamhyr_date(int(v))
|
||||
else:
|
||||
value = str(
|
||||
value = format_datetime(
|
||||
self._start_date + timedelta(seconds=float(v))
|
||||
)
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ from tools import (
|
|||
trace, timer,
|
||||
timestamp_to_old_pamhyr_date,
|
||||
old_pamhyr_date_to_timestamp,
|
||||
timestamp_to_old_pamhyr_date_adists
|
||||
timestamp_to_old_pamhyr_date_adists, format_datetime
|
||||
)
|
||||
|
||||
from View.Tools.PamhyrTable import PamhyrTableModel
|
||||
|
|
@ -90,7 +90,7 @@ class TableModel(PamhyrTableModel):
|
|||
if self._opt_data == "time":
|
||||
value = timestamp_to_old_pamhyr_date_adists(int(v))
|
||||
else:
|
||||
value = str(
|
||||
value = format_datetime(
|
||||
self._start_date + timedelta(seconds=float(v))
|
||||
)
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -19,9 +19,7 @@
|
|||
import logging
|
||||
import traceback
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from tools import trace, timer
|
||||
from tools import trace, timer, parse_datetime
|
||||
|
||||
from Model.Except import NotImplementedMethodeError
|
||||
|
||||
|
|
@ -36,8 +34,11 @@ from PyQt5.QtWidgets import (
|
|||
QFileDialog, QTableView, QAbstractItemView,
|
||||
QUndoStack, QShortcut, QAction, QItemDelegate,
|
||||
QComboBox, QStyledItemDelegate, QHeaderView,
|
||||
QMessageBox,
|
||||
)
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
|
||||
|
|
@ -63,9 +64,22 @@ class PamhyrTextDelegate(QStyledItemDelegate):
|
|||
class PamhyrTableModel(QAbstractTableModel):
|
||||
def date_to_elapsed_seconds(self, value):
|
||||
"""Convert an entered date to seconds since the study start date."""
|
||||
entered_date = value
|
||||
if not isinstance(entered_date, datetime):
|
||||
entered_date = datetime.fromisoformat(str(value).strip())
|
||||
try:
|
||||
entered_date = parse_datetime(value)
|
||||
except ValueError as error:
|
||||
QMessageBox.warning(
|
||||
self._table_view,
|
||||
_translate("PamhyrTableModel", "Invalid date/time"),
|
||||
_translate(
|
||||
"PamhyrTableModel",
|
||||
"The entered date/time is invalid.\n"
|
||||
"Expected formats:\n"
|
||||
"YYYY-MM-DD [HH:MM[:SS]],\n"
|
||||
"DD-MM-YYYY [HH:MM[:SS]] or\n"
|
||||
"DD/MM/YYYY [HH:MM[:SS]]."
|
||||
)
|
||||
)
|
||||
raise error
|
||||
|
||||
return (entered_date - self._start_date).total_seconds()
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ from datetime import date, time, datetime, timedelta
|
|||
from tools import (
|
||||
trace, timer,
|
||||
timestamp_to_old_pamhyr_date,
|
||||
old_pamhyr_date_to_timestamp
|
||||
old_pamhyr_date_to_timestamp, format_datetime
|
||||
)
|
||||
|
||||
from View.Tools.PamhyrTable import PamhyrTableModel
|
||||
|
|
@ -77,7 +77,7 @@ class TableModel(PamhyrTableModel):
|
|||
if self._opt_data == "time":
|
||||
value = timestamp_to_old_pamhyr_date(int(v))
|
||||
else:
|
||||
value = str(
|
||||
value = format_datetime(
|
||||
self._start_date + timedelta(seconds=float(v))
|
||||
)
|
||||
else:
|
||||
|
|
|
|||
53
src/tools.py
53
src/tools.py
|
|
@ -22,7 +22,7 @@ import logging
|
|||
import sqlite3
|
||||
import traceback
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from pathlib import Path
|
||||
|
||||
from colorama import Fore
|
||||
|
|
@ -239,6 +239,57 @@ def timestamp(dt: datetime):
|
|||
return dt.timestamp()
|
||||
|
||||
|
||||
SUPPORTED_DATETIME_FORMATS = (
|
||||
"%d-%m-%Y %H:%M:%S.%f",
|
||||
"%d-%m-%Y %H:%M:%S",
|
||||
"%d-%m-%Y %H:%M",
|
||||
"%d-%m-%Y",
|
||||
"%d/%m/%Y %H:%M:%S.%f",
|
||||
"%d/%m/%Y %H:%M:%S",
|
||||
"%d/%m/%Y %H:%M",
|
||||
"%d/%m/%Y",
|
||||
"%d-%m-%y %H:%M:%S",
|
||||
"%d/%m/%y %H:%M:%S",
|
||||
)
|
||||
|
||||
|
||||
def parse_datetime(value):
|
||||
"""Parse a supported date representation into a naive UTC datetime."""
|
||||
if isinstance(value, datetime):
|
||||
parsed = value
|
||||
else:
|
||||
text = str(value).strip()
|
||||
if text.endswith(("Z", "z")):
|
||||
text = text[:-1] + "+00:00"
|
||||
|
||||
try:
|
||||
parsed = datetime.fromisoformat(text)
|
||||
except ValueError as iso_error:
|
||||
for date_format in SUPPORTED_DATETIME_FORMATS:
|
||||
try:
|
||||
parsed = datetime.strptime(text, date_format)
|
||||
break
|
||||
except ValueError:
|
||||
continue
|
||||
else:
|
||||
raise ValueError(
|
||||
f"Unsupported date format: {value!r}. Expected an ISO "
|
||||
"date/time or one of: "
|
||||
+ ", ".join(SUPPORTED_DATETIME_FORMATS)
|
||||
) from iso_error
|
||||
|
||||
# If the parsed datetime has timezone information, convert it to UTC and remove the timezone info
|
||||
if parsed.tzinfo is not None:
|
||||
parsed = parsed.astimezone(timezone.utc).replace(tzinfo=None)
|
||||
|
||||
return parsed
|
||||
|
||||
|
||||
def format_datetime(value):
|
||||
"""Return a datetime using the canonical application format."""
|
||||
return parse_datetime(value).strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
|
||||
def date_iso_to_timestamp(date: str):
|
||||
if type(date) is str:
|
||||
return timestamp(datetime.fromisoformat(date))
|
||||
|
|
|
|||
Loading…
Reference in New Issue