mirror of https://gitlab.com/pamhyr/pamhyr2
Merge branch 'mesh_tab' into dev_dylan
commit
53da35d959
|
|
@ -24,7 +24,7 @@ from datetime import date, time, datetime, timedelta
|
||||||
from tools import (
|
from tools import (
|
||||||
trace, timer,
|
trace, timer,
|
||||||
timestamp_to_old_pamhyr_date,
|
timestamp_to_old_pamhyr_date,
|
||||||
old_pamhyr_date_to_timestamp
|
old_pamhyr_date_to_timestamp, format_datetime
|
||||||
)
|
)
|
||||||
|
|
||||||
from View.Tools.PamhyrTable import PamhyrTableModel
|
from View.Tools.PamhyrTable import PamhyrTableModel
|
||||||
|
|
@ -97,7 +97,9 @@ class TableModel(PamhyrTableModel):
|
||||||
if self._opt_data == "time":
|
if self._opt_data == "time":
|
||||||
value = timestamp_to_old_pamhyr_date(int(v))
|
value = timestamp_to_old_pamhyr_date(int(v))
|
||||||
else:
|
else:
|
||||||
value = str(datetime.fromtimestamp(v))
|
value = format_datetime(
|
||||||
|
self._start_date + timedelta(seconds=float(v))
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
value = f"{v}"
|
value = f"{v}"
|
||||||
|
|
||||||
|
|
@ -114,6 +116,10 @@ class TableModel(PamhyrTableModel):
|
||||||
column = index.column()
|
column = index.column()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
if (self._data.header[column] == "time"
|
||||||
|
and self._opt_data == "date"):
|
||||||
|
value = self.date_to_elapsed_seconds(value)
|
||||||
|
|
||||||
row = self.get_true_data_row(row)
|
row = self.get_true_data_row(row)
|
||||||
|
|
||||||
self._undo.push(
|
self._undo.push(
|
||||||
|
|
|
||||||
|
|
@ -173,7 +173,8 @@ class EditBoundaryConditionWindow(PamhyrWindow):
|
||||||
},
|
},
|
||||||
data=self._data,
|
data=self._data,
|
||||||
undo=self._undo_stack,
|
undo=self._undo_stack,
|
||||||
opt_data=self._study.time_system
|
opt_data=self._study.time_system,
|
||||||
|
start_date=self._study.date
|
||||||
)
|
)
|
||||||
|
|
||||||
table.setModel(self._table)
|
table.setModel(self._table)
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ from datetime import date, time, datetime, timedelta
|
||||||
from tools import (
|
from tools import (
|
||||||
trace, timer,
|
trace, timer,
|
||||||
timestamp_to_old_pamhyr_date,
|
timestamp_to_old_pamhyr_date,
|
||||||
old_pamhyr_date_to_timestamp
|
old_pamhyr_date_to_timestamp, format_datetime
|
||||||
)
|
)
|
||||||
|
|
||||||
from View.Tools.PamhyrTable import PamhyrTableModel
|
from View.Tools.PamhyrTable import PamhyrTableModel
|
||||||
|
|
@ -87,7 +87,9 @@ class TableModel(PamhyrTableModel):
|
||||||
if self._opt_data == "time":
|
if self._opt_data == "time":
|
||||||
value = timestamp_to_old_pamhyr_date(int(v))
|
value = timestamp_to_old_pamhyr_date(int(v))
|
||||||
else:
|
else:
|
||||||
value = str(datetime.fromtimestamp(v))
|
value = format_datetime(
|
||||||
|
self._start_date + timedelta(seconds=float(v))
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
value = f"{v}"
|
value = f"{v}"
|
||||||
|
|
||||||
|
|
@ -104,6 +106,10 @@ class TableModel(PamhyrTableModel):
|
||||||
column = index.column()
|
column = index.column()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
if (self._data.header[column] == "time"
|
||||||
|
and self._opt_data == "date"):
|
||||||
|
value = self.date_to_elapsed_seconds(value)
|
||||||
|
|
||||||
row = self.get_true_data_row(row)
|
row = self.get_true_data_row(row)
|
||||||
|
|
||||||
self._undo.push(
|
self._undo.push(
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,8 @@ class EditBoundaryConditionWindow(PamhyrWindow):
|
||||||
},
|
},
|
||||||
data=self._data,
|
data=self._data,
|
||||||
undo=self._undo_stack,
|
undo=self._undo_stack,
|
||||||
opt_data=self._study.time_system
|
opt_data=self._study.time_system,
|
||||||
|
start_date=self._study.date
|
||||||
)
|
)
|
||||||
|
|
||||||
table.setModel(self._table)
|
table.setModel(self._table)
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ from datetime import date, time, datetime, timedelta
|
||||||
from tools import (
|
from tools import (
|
||||||
trace, timer,
|
trace, timer,
|
||||||
timestamp_to_old_pamhyr_date,
|
timestamp_to_old_pamhyr_date,
|
||||||
old_pamhyr_date_to_timestamp
|
old_pamhyr_date_to_timestamp, format_datetime
|
||||||
)
|
)
|
||||||
|
|
||||||
from View.Tools.PamhyrTable import PamhyrTableModel
|
from View.Tools.PamhyrTable import PamhyrTableModel
|
||||||
|
|
@ -87,7 +87,9 @@ class TableModel(PamhyrTableModel):
|
||||||
if self._opt_data == "time":
|
if self._opt_data == "time":
|
||||||
value = timestamp_to_old_pamhyr_date(int(v))
|
value = timestamp_to_old_pamhyr_date(int(v))
|
||||||
else:
|
else:
|
||||||
value = str(datetime.fromtimestamp(v))
|
value = format_datetime(
|
||||||
|
self._start_date + timedelta(seconds=float(v))
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
value = f"{v}"
|
value = f"{v}"
|
||||||
|
|
||||||
|
|
@ -104,6 +106,10 @@ class TableModel(PamhyrTableModel):
|
||||||
column = index.column()
|
column = index.column()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
if (self._data.header[column] == "time"
|
||||||
|
and self._opt_data == "date"):
|
||||||
|
value = self.date_to_elapsed_seconds(value)
|
||||||
|
|
||||||
row = self.get_true_data_row(row)
|
row = self.get_true_data_row(row)
|
||||||
|
|
||||||
self._undo.push(
|
self._undo.push(
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,8 @@ class EditBoundaryConditionWindow(PamhyrWindow):
|
||||||
},
|
},
|
||||||
data=self._data,
|
data=self._data,
|
||||||
undo=self._undo_stack,
|
undo=self._undo_stack,
|
||||||
opt_data=self._study.time_system
|
opt_data=self._study.time_system,
|
||||||
|
start_date=self._study.date
|
||||||
)
|
)
|
||||||
|
|
||||||
table.setModel(self._table)
|
table.setModel(self._table)
|
||||||
|
|
|
||||||
|
|
@ -171,7 +171,7 @@ class ProfileWindow(PamhyrWindow):
|
||||||
|
|
||||||
def profiles(self):
|
def profiles(self):
|
||||||
"""Return profiles from the geometry model owning this profile."""
|
"""Return profiles from the geometry model owning this profile."""
|
||||||
return self._profile.reach.reach.profiles
|
return self._profile.reach.profiles
|
||||||
|
|
||||||
def navigate_profile(self, offset):
|
def navigate_profile(self, offset):
|
||||||
profiles = self.profiles()
|
profiles = self.profiles()
|
||||||
|
|
|
||||||
|
|
@ -818,6 +818,10 @@ class GeometryWindow(PamhyrWindow):
|
||||||
# self.update_plot_rkc()
|
# self.update_plot_rkc()
|
||||||
|
|
||||||
def export_to_file(self):
|
def export_to_file(self):
|
||||||
|
export_interpolated = self._ask_export_options()
|
||||||
|
if export_interpolated is None:
|
||||||
|
return
|
||||||
|
|
||||||
settings = QSettings(
|
settings = QSettings(
|
||||||
QSettings.IniFormat,
|
QSettings.IniFormat,
|
||||||
QSettings.UserScope, 'MyOrg'
|
QSettings.UserScope, 'MyOrg'
|
||||||
|
|
@ -847,11 +851,9 @@ class GeometryWindow(PamhyrWindow):
|
||||||
suffix = Path(filename).suffix
|
suffix = Path(filename).suffix
|
||||||
if suffix != "":
|
if suffix != "":
|
||||||
if suffix == ".st" or suffix == ".ST":
|
if suffix == ".st" or suffix == ".ST":
|
||||||
export_interpolated = self._ask_export_options()
|
self._export_to_file_st(
|
||||||
if export_interpolated is not None:
|
filename[:-3], export_interpolated
|
||||||
self._export_to_file_st(
|
)
|
||||||
filename[:-3], export_interpolated
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
# Warning popup when the format is not exportable
|
# Warning popup when the format is not exportable
|
||||||
win = QtWidgets.QMessageBox()
|
win = QtWidgets.QMessageBox()
|
||||||
|
|
@ -862,9 +864,7 @@ class GeometryWindow(PamhyrWindow):
|
||||||
|
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
export_interpolated = self._ask_export_options()
|
self._export_to_file_st(filename, export_interpolated)
|
||||||
if export_interpolated is not None:
|
|
||||||
self._export_to_file_st(filename, export_interpolated)
|
|
||||||
|
|
||||||
def _ask_export_options(self):
|
def _ask_export_options(self):
|
||||||
win = QtWidgets.QMessageBox(self)
|
win = QtWidgets.QMessageBox(self)
|
||||||
|
|
@ -901,8 +901,9 @@ class GeometryWindow(PamhyrWindow):
|
||||||
if is_interpolated and not export_interpolated:
|
if is_interpolated and not export_interpolated:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
self._export_to_file_st_profile(wfile, profile, pid)
|
if profile.enabled:
|
||||||
pid += 1
|
self._export_to_file_st_profile(wfile, profile, pid)
|
||||||
|
pid += 1
|
||||||
|
|
||||||
def _export_to_file_st_profile(self, wfile, profile, pid):
|
def _export_to_file_st_profile(self, wfile, profile, pid):
|
||||||
num = f"{pid:>6}"
|
num = f"{pid:>6}"
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ from datetime import date, time, datetime, timedelta
|
||||||
from tools import (
|
from tools import (
|
||||||
trace, timer,
|
trace, timer,
|
||||||
timestamp_to_old_pamhyr_date,
|
timestamp_to_old_pamhyr_date,
|
||||||
old_pamhyr_date_to_timestamp
|
old_pamhyr_date_to_timestamp, format_datetime
|
||||||
)
|
)
|
||||||
|
|
||||||
from View.Tools.PamhyrTable import PamhyrTableModel
|
from View.Tools.PamhyrTable import PamhyrTableModel
|
||||||
|
|
@ -76,7 +76,9 @@ class TableModel(PamhyrTableModel):
|
||||||
if self._opt_data == "time":
|
if self._opt_data == "time":
|
||||||
value = timestamp_to_old_pamhyr_date(int(v))
|
value = timestamp_to_old_pamhyr_date(int(v))
|
||||||
else:
|
else:
|
||||||
value = str(datetime.fromtimestamp(v))
|
value = format_datetime(
|
||||||
|
self._start_date + timedelta(seconds=float(v))
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
value = f"{v}"
|
value = f"{v}"
|
||||||
|
|
||||||
|
|
@ -93,6 +95,10 @@ class TableModel(PamhyrTableModel):
|
||||||
column = index.column()
|
column = index.column()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
if (self._data.header[column] == "time"
|
||||||
|
and self._opt_data == "date"):
|
||||||
|
value = self.date_to_elapsed_seconds(value)
|
||||||
|
|
||||||
self._undo.push(
|
self._undo.push(
|
||||||
SetDataCommand(
|
SetDataCommand(
|
||||||
self._data, row, column, value
|
self._data, row, column, value
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,8 @@ class EditLateralContributionWindow(PamhyrWindow):
|
||||||
data=self._data,
|
data=self._data,
|
||||||
undo=self._undo_stack,
|
undo=self._undo_stack,
|
||||||
trad=self._trad,
|
trad=self._trad,
|
||||||
opt_data=self._study.time_system
|
opt_data=self._study.time_system,
|
||||||
|
start_date=self._study.date
|
||||||
)
|
)
|
||||||
|
|
||||||
table.setModel(self._table)
|
table.setModel(self._table)
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ from tools import (
|
||||||
trace, timer,
|
trace, timer,
|
||||||
timestamp_to_old_pamhyr_date,
|
timestamp_to_old_pamhyr_date,
|
||||||
old_pamhyr_date_to_timestamp,
|
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
|
from View.Tools.PamhyrTable import PamhyrTableModel
|
||||||
|
|
@ -90,7 +90,9 @@ class TableModel(PamhyrTableModel):
|
||||||
if self._opt_data == "time":
|
if self._opt_data == "time":
|
||||||
value = timestamp_to_old_pamhyr_date_adists(int(v))
|
value = timestamp_to_old_pamhyr_date_adists(int(v))
|
||||||
else:
|
else:
|
||||||
value = str(datetime.fromtimestamp(v))
|
value = format_datetime(
|
||||||
|
self._start_date + timedelta(seconds=float(v))
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
value = f"{v}"
|
value = f"{v}"
|
||||||
|
|
||||||
|
|
@ -107,6 +109,10 @@ class TableModel(PamhyrTableModel):
|
||||||
column = index.column()
|
column = index.column()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
if (self._data.header[column] == "time"
|
||||||
|
and self._opt_data == "date"):
|
||||||
|
value = self.date_to_elapsed_seconds(value)
|
||||||
|
|
||||||
row = self.get_true_data_row(row)
|
row = self.get_true_data_row(row)
|
||||||
|
|
||||||
self._undo.push(
|
self._undo.push(
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,8 @@ class EditLateralContributionAdisTSWindow(PamhyrWindow):
|
||||||
data=self._data,
|
data=self._data,
|
||||||
undo=self._undo_stack,
|
undo=self._undo_stack,
|
||||||
trad=self._trad,
|
trad=self._trad,
|
||||||
opt_data=self._study.time_system
|
opt_data=self._study.time_system,
|
||||||
|
start_date=self._study.date
|
||||||
)
|
)
|
||||||
|
|
||||||
table.setModel(self._table)
|
table.setModel(self._table)
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
import logging
|
import logging
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from tools import trace, timer
|
from tools import trace, timer, parse_datetime
|
||||||
|
|
||||||
from Model.Except import NotImplementedMethodeError
|
from Model.Except import NotImplementedMethodeError
|
||||||
|
|
||||||
|
|
@ -34,8 +34,11 @@ from PyQt5.QtWidgets import (
|
||||||
QFileDialog, QTableView, QAbstractItemView,
|
QFileDialog, QTableView, QAbstractItemView,
|
||||||
QUndoStack, QShortcut, QAction, QItemDelegate,
|
QUndoStack, QShortcut, QAction, QItemDelegate,
|
||||||
QComboBox, QStyledItemDelegate, QHeaderView,
|
QComboBox, QStyledItemDelegate, QHeaderView,
|
||||||
|
QMessageBox,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -59,6 +62,27 @@ class PamhyrTextDelegate(QStyledItemDelegate):
|
||||||
|
|
||||||
|
|
||||||
class PamhyrTableModel(QAbstractTableModel):
|
class PamhyrTableModel(QAbstractTableModel):
|
||||||
|
def date_to_elapsed_seconds(self, value):
|
||||||
|
"""Convert an entered date to seconds since the study start date."""
|
||||||
|
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()
|
||||||
|
|
||||||
def _setup_delegates(self):
|
def _setup_delegates(self):
|
||||||
if self._table_view is None:
|
if self._table_view is None:
|
||||||
return
|
return
|
||||||
|
|
@ -85,7 +109,8 @@ class PamhyrTableModel(QAbstractTableModel):
|
||||||
undo=None,
|
undo=None,
|
||||||
opt_data=None,
|
opt_data=None,
|
||||||
options=["rows_selection"],
|
options=["rows_selection"],
|
||||||
parent=None):
|
parent=None,
|
||||||
|
start_date=None):
|
||||||
super(PamhyrTableModel, self).__init__()
|
super(PamhyrTableModel, self).__init__()
|
||||||
|
|
||||||
self._table_view = table_view
|
self._table_view = table_view
|
||||||
|
|
@ -102,6 +127,7 @@ class PamhyrTableModel(QAbstractTableModel):
|
||||||
self._options = options
|
self._options = options
|
||||||
self._undo = undo
|
self._undo = undo
|
||||||
self._lst = []
|
self._lst = []
|
||||||
|
self._start_date = start_date
|
||||||
|
|
||||||
self._setup_delegates()
|
self._setup_delegates()
|
||||||
self._setup_lst()
|
self._setup_lst()
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ from datetime import date, time, datetime, timedelta
|
||||||
from tools import (
|
from tools import (
|
||||||
trace, timer,
|
trace, timer,
|
||||||
timestamp_to_old_pamhyr_date,
|
timestamp_to_old_pamhyr_date,
|
||||||
old_pamhyr_date_to_timestamp
|
old_pamhyr_date_to_timestamp, format_datetime
|
||||||
)
|
)
|
||||||
|
|
||||||
from View.Tools.PamhyrTable import PamhyrTableModel
|
from View.Tools.PamhyrTable import PamhyrTableModel
|
||||||
|
|
@ -77,7 +77,9 @@ class TableModel(PamhyrTableModel):
|
||||||
if self._opt_data == "time":
|
if self._opt_data == "time":
|
||||||
value = timestamp_to_old_pamhyr_date(int(v))
|
value = timestamp_to_old_pamhyr_date(int(v))
|
||||||
else:
|
else:
|
||||||
value = str(datetime.fromtimestamp(v))
|
value = format_datetime(
|
||||||
|
self._start_date + timedelta(seconds=float(v))
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
value = f"{v}"
|
value = f"{v}"
|
||||||
|
|
||||||
|
|
@ -94,6 +96,10 @@ class TableModel(PamhyrTableModel):
|
||||||
column = index.column()
|
column = index.column()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
if (self._data.header[column] == "time"
|
||||||
|
and self._opt_data == "date"):
|
||||||
|
value = self.date_to_elapsed_seconds(value)
|
||||||
|
|
||||||
self._undo.push(
|
self._undo.push(
|
||||||
SetDataCommand(
|
SetDataCommand(
|
||||||
self._data, row, column, value
|
self._data, row, column, value
|
||||||
|
|
|
||||||
|
|
@ -121,7 +121,8 @@ class EditWeatherParametersWindow(PamhyrWindow):
|
||||||
data=self._data,
|
data=self._data,
|
||||||
undo=self._undo_stack,
|
undo=self._undo_stack,
|
||||||
trad=self._trad,
|
trad=self._trad,
|
||||||
opt_data=self._study.time_system
|
opt_data=self._study.time_system,
|
||||||
|
start_date=self._study.date
|
||||||
)
|
)
|
||||||
|
|
||||||
table.setModel(self._table)
|
table.setModel(self._table)
|
||||||
|
|
|
||||||
53
src/tools.py
53
src/tools.py
|
|
@ -22,7 +22,7 @@ import logging
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta, timezone
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from colorama import Fore
|
from colorama import Fore
|
||||||
|
|
@ -239,6 +239,57 @@ def timestamp(dt: datetime):
|
||||||
return dt.timestamp()
|
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):
|
def date_iso_to_timestamp(date: str):
|
||||||
if type(date) is str:
|
if type(date) is str:
|
||||||
return timestamp(datetime.fromisoformat(date))
|
return timestamp(datetime.fromisoformat(date))
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue