fix: display db timestamps in Brussels time

(heure de dépôt was showing UTC)

- feat: add date_depot column (real TFE deposit date)
with CSV round-trip + Brussels→UTC sanitization
- fix: keep PHP default tz at UTC to preserve token/share-link
 expiry consistency; convert to Brussels only in db_datetime()
This commit is contained in:
Pontoporeia
2026-09-18 16:26:36 +02:00
parent 2232981753
commit 30a16f9e9e
13 changed files with 280 additions and 9 deletions
+50 -2
View File
@@ -143,6 +143,51 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['csv_file'])) {
return ($raw === 'oui' || $raw === '1' || $raw === 'yes' || $raw === 'true') ? 1 : 0;
};
// Helper: parse a bulk-import date cell into a UTC 'Y-m-d H:i:s' string.
// The cell is authored in Brussels local time (e.g. "12/05/2026",
// "12/05/2026 14:30", ISO "2026-05-12"). We interpret it in the
// Europe/Brussels timezone and convert to UTC for storage, matching
// the rest of the DB (SQLite CURRENT_TIMESTAMP) and the db_datetime()
// display helper which converts UTC → Brussels on read.
$parseBulkDate = function(string $raw): ?string {
$raw = trim($raw);
if ($raw === '') return null;
// Try a set of formats (d/m/Y first — the CSV convention).
// Date-only formats (no time component) are anchored to midnight
// local time; PHP otherwise fills a missing time with *now*.
$formats = [
'd/m/Y H:i:s', 'd/m/Y H:i', 'd/m/Y',
'Y-m-d H:i:s', 'Y-m-d H:i', 'Y-m-d',
'd.m.Y H:i', 'd.m.Y',
];
foreach ($formats as $fmt) {
$dt = DateTime::createFromFormat($fmt, $raw, new DateTimeZone('Europe/Brussels'));
if ($dt === false) {
continue;
}
// Reject partial parses (e.g. "12/05/20xx" residual garbage).
$errors = DateTime::getLastErrors();
if ($errors && ($errors['warning_count'] > 0 || $errors['error_count'] > 0)) {
continue;
}
// Anchor date-only values to midnight local time.
if (!str_contains($fmt, 'H') && !str_contains($fmt, ':')) {
$dt->setTime(0, 0, 0);
}
$dt->setTimezone(new DateTimeZone('UTC'));
return $dt->format('Y-m-d H:i:s');
}
// ISO fallback via strtotime (assumes Brussels for naive strings).
$ts = strtotime($raw . ' Europe/Brussels');
if ($ts !== false) {
return gmdate('Y-m-d H:i:s', $ts);
}
return null;
};
// Code → canonical name (legacy short-code CSV format)
$orientationCodeMap = [
'SC'=>'Sculpture','VI'=>'Vidéographie','CA'=>"Cinéma d'animation",
@@ -305,6 +350,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['csv_file'])) {
$contactVisible = $cell($row, 'contact-visible'); // second "contact", key won't match header → positional
$objetRaw = $cell($row, 'objet');
$objet = in_array($objetRaw, ['tfe', 'thèse', 'frart'], true) ? $objetRaw : 'tfe';
$dateDepotRaw = $cell($row, 'dépôt');
$dateDepot = parseBulkDate($dateDepotRaw); // Brussels-local → UTC (Y-m-d H:i:s) or null
if ($title === '' || $year === 0) {
$missing = [];
@@ -366,8 +413,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['csv_file'])) {
cc2r, exemplaire_baiu, exemplaire_erg,
objet, contact_visible,
duration_pages, duration_minutes, has_annexes,
is_published, status, submitted_at
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,0,'active',CURRENT_TIMESTAMP)
is_published, status, submitted_at, date_depot
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,0,'active',CURRENT_TIMESTAMP,?)
");
$s->execute([
!empty($identifier) ? $identifier : null, $title,
@@ -389,6 +436,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['csv_file'])) {
$durationPages,
$durationMinutes,
$hasAnnexes,
$dateDepot,
]);
$thesisId = $importPdo->lastInsertId();