From 1e863ade5d0f72670ac2f549b189f7bc1415c70e Mon Sep 17 00:00:00 2001 From: Andreas Kristiansen <6977712+AndreasK79@users.noreply.github.com> Date: Mon, 14 Jul 2025 14:02:20 +0200 Subject: [PATCH] [QSO entry] Custom date format --- application/controllers/Logbook.php | 19 +++++++++- application/models/Logbook_model.php | 52 ++++++++++++++++++++------ application/views/qso/index.php | 34 +++++++++++++++-- assets/js/sections/qso.js | 55 +++++++++++++++++++++++++--- 4 files changed, 136 insertions(+), 24 deletions(-) diff --git a/application/controllers/Logbook.php b/application/controllers/Logbook.php index b264715ce..f9247db90 100644 --- a/application/controllers/Logbook.php +++ b/application/controllers/Logbook.php @@ -76,8 +76,23 @@ class Logbook extends CI_Controller { function json($tempcallsign, $tempband, $tempmode, $tempstation_id = null, $date = "", $count = 5) { session_write_close(); - if (($date ?? '') != '') { - $date=date("Y-m-d",strtotime($date)); + + // Normalize the date only if it's not empty + if (!empty($date)) { + // Get user-preferred date format + if ($this->session->userdata('user_date_format')) { + $date_format = $this->session->userdata('user_date_format'); + } else { + $date_format = $this->config->item('qso_date_format'); + } + $date = urldecode($date); + $dt = DateTime::createFromFormat($date_format, $date); + if ($dt !== false) { + $date = $dt->format('Y-m-d'); // or any normalized format + } else { + // Invalid date for the expected format, handle gracefully + $date = null; + } } // Cleaning for security purposes $callsign = $this->security->xss_clean($tempcallsign); diff --git a/application/models/Logbook_model.php b/application/models/Logbook_model.php index bd0cda7c0..b16c04d5d 100644 --- a/application/models/Logbook_model.php +++ b/application/models/Logbook_model.php @@ -17,20 +17,48 @@ class Logbook_model extends CI_Model { /* Add QSO to Logbook */ function create_qso() { + // Get user-preferred date format + if ($this->session->userdata('user_date_format')) { + $date_format = $this->session->userdata('user_date_format'); + } else { + $date_format = $this->config->item('qso_date_format'); + } + + // Get input values + $start_date = $this->input->post('start_date'); // e.g., "14/07/2025" + $start_time = $this->input->post('start_time'); // e.g., "08:11:36" + $end_time = $this->input->post('end_time'); // e.g., "00:05:00" (optional) $callsign = trim(str_replace('Ø', '0', $this->input->post('callsign'))); - // Join date+time - $datetime = date("Y-m-d", strtotime($this->input->post('start_date'))) . " " . $this->input->post('start_time'); - if (($this->input->post('end_time') ?? '') != '') { - $datetime_off = date("Y-m-d", strtotime($this->input->post('start_date'))) . " " . $this->input->post('end_time'); - // if time off < time on, and time off is on 00:xx >> add 1 day (concidering start and end are between 23:00 and 00:59) // - $_tmp_datetime_off = strtotime($datetime_off); - if (($_tmp_datetime_off < strtotime($datetime)) && (substr($this->input->post('end_time'), 0, 2) == "00")) { - $datetime_off = date("Y-m-d H:i:s", ($_tmp_datetime_off + 60 * 60 * 24)); - } + + // Parse datetime using createFromFormat + $datetime_obj = DateTime::createFromFormat("$date_format H:i:s", "$start_date $start_time"); + + if ($datetime_obj === false) { + // Handle parse error gracefully (optional: log error) + $datetime = null; + $datetime_off = null; } else { - $datetime_off = $datetime; + $datetime = $datetime_obj->format('Y-m-d H:i:s'); // Standard format for DB + + // Handle end time + if (!empty($end_time)) { + $end_datetime_obj = DateTime::createFromFormat("$date_format H:i:s", "$start_date $end_time"); + + if ($end_datetime_obj === false) { + $datetime_off = $datetime; + } else { + // If time-off is before time-on and hour is 00 → add 1 day + if ($end_datetime_obj < $datetime_obj && str_starts_with($end_time, "00")) { + $end_datetime_obj->modify('+1 day'); + } + $datetime_off = $end_datetime_obj->format('Y-m-d H:i:s'); + } + } else { + $datetime_off = $datetime; + } } + if ($this->input->post('prop_mode') != null) { $prop_mode = $this->input->post('prop_mode'); } else { @@ -181,7 +209,7 @@ class Logbook_model extends CI_Model { // Represent cnty with "state,cnty" only for USA // Others do no need it - + if ($this->input->post('county') && $this->input->post('input_state')) { switch ($dxcc_id) { case 6: @@ -1320,7 +1348,7 @@ class Logbook_model extends CI_Model { } else { // nothing from above? $uscounty = null; } - + } else { $retvals['detail']=__("DXCC has to be Numeric"); return $retvals; diff --git a/application/views/qso/index.php b/application/views/qso/index.php index cf246e6ef..93586d393 100644 --- a/application/views/qso/index.php +++ b/application/views/qso/index.php @@ -1,4 +1,29 @@
+session->userdata('user_date_format')) { + // If Logged in and session exists + $date_format = $this->session->userdata('user_date_format'); +} else { + // Get Default date format from /config/wavelog.php + $date_format = $this->config->item('qso_date_format'); +} + +// Convert PHP date format to appropriate input pattern for validation +switch ($date_format) { + case "d/m/y": $current_pattern = '[0-3][0-9]/[0-1][0-9]/[0-9]{2}'; break; + case "d/m/Y": $current_pattern = '[0-3][0-9]/[0-1][0-9]/[0-9]{4}'; break; + case "m/d/y": $current_pattern = '[0-1][0-9]/[0-3][0-9]/[0-9]{2}'; break; + case "m/d/Y": $current_pattern = '[0-1][0-9]/[0-3][0-9]/[0-9]{4}'; break; + case "d.m.Y": $current_pattern = '[0-3][0-9]\.[0-1][0-9]\.[0-9]{4}'; break; + case "y/m/d": $current_pattern = '[0-9]{2}/[0-1][0-9]/[0-3][0-9]'; break; + case "Y-m-d": $current_pattern = '[0-9]{4}-[0-1][0-9]-[0-3][0-9]'; break; + case "M d, Y": $current_pattern = '[A-Za-z]{3}\s[0-3][0-9],\s[0-9]{4}'; break; + case "M d, y": $current_pattern = '[A-Za-z]{3}\s[0-3][0-9],\s[0-9]{2}'; break; + default: $current_pattern = '[0-3][0-9]-[0-1][0-9]-[0-9]{4}'; $date_format = 'd-m-Y'; +} +?> +
@@ -69,7 +95,7 @@
- required pattern="[0-3][0-9]-[0-1][0-9]-[0-9]{4}"> + required pattern="">
@@ -97,7 +123,7 @@ - +
@@ -105,7 +131,7 @@
- required pattern="[0-3][0-9]-[0-1][0-9]-[0-9]{4}"> + required pattern="">
@@ -120,7 +146,7 @@ - +
diff --git a/assets/js/sections/qso.js b/assets/js/sections/qso.js index d68d2511e..6a61c6e51 100644 --- a/assets/js/sections/qso.js +++ b/assets/js/sections/qso.js @@ -27,7 +27,50 @@ function getUTCTimeStamp(el) { function getUTCDateStamp(el) { var now = new Date(); - $(el).attr('value', ("0" + now.getUTCDate()).slice(-2) + '-' + ("0" + (now.getUTCMonth() + 1)).slice(-2) + '-' + now.getUTCFullYear()); + var day = ("0" + now.getUTCDate()).slice(-2); + var month = ("0" + (now.getUTCMonth() + 1)).slice(-2); + var year = now.getUTCFullYear(); + var short_year = year.toString().slice(-2); + + // Format the date based on user_date_format passed from PHP + var formatted_date; + switch (user_date_format) { + case "d/m/y": + formatted_date = day + "/" + month + "/" + short_year; + break; + case "d/m/Y": + formatted_date = day + "/" + month + "/" + year; + break; + case "m/d/y": + formatted_date = month + "/" + day + "/" + short_year; + break; + case "m/d/Y": + formatted_date = month + "/" + day + "/" + year; + break; + case "d.m.Y": + formatted_date = day + "." + month + "." + year; + break; + case "y/m/d": + formatted_date = short_year + "/" + month + "/" + day; + break; + case "Y-m-d": + formatted_date = year + "-" + month + "-" + day; + break; + case "M d, Y": + // Need to get the month name abbreviation + var monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; + formatted_date = monthNames[now.getUTCMonth()] + " " + parseInt(day) + ", " + year; + break; + case "M d, y": + var monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; + formatted_date = monthNames[now.getUTCMonth()] + " " + parseInt(day) + ", " + short_year; + break; + default: + // Default to d-m-Y format as shown in the PHP code + formatted_date = day + "-" + month + "-" + year; + } + + $(el).attr('value', formatted_date); } @@ -777,9 +820,6 @@ $("#callsign").on("focusout", function () { $("#noticer").fadeOut(1000); - // Temp store the callsign - var temp_callsign = $(this).val(); - /* Find and populate DXCC */ $('.callsign-suggest').hide(); @@ -788,16 +828,19 @@ $("#callsign").on("focusout", function () { } else { var json_band = $("#band").val(); } - var json_mode = $("#mode").val(); + const json_mode = $("#mode").val(); var find_callsign = $(this).val().toUpperCase(); var callsign = find_callsign; + const startDate = encodeURIComponent($('#start_date').val()); + const stationProfile = $('#stationProfile').val(); find_callsign = find_callsign.replace(/\//g, "-"); find_callsign = find_callsign.replaceAll('Ø', '0'); + const url = `${base_url}index.php/logbook/json/${find_callsign}/${json_band}/${json_mode}/${stationProfile}/${startDate}/${last_qsos_count}`; // Replace / in a callsign with - to stop urls breaking - lookupCall = $.getJSON(base_url + 'index.php/logbook/json/' + find_callsign + '/' + json_band + '/' + json_mode + '/' + $('#stationProfile').val() + '/' + $('#start_date').val() + '/' + last_qsos_count, async function (result) { + lookupCall = $.getJSON(url, async function (result) { // Make sure the typed callsign and json result match if ($('#callsign').val().toUpperCase().replaceAll('Ø', '0') == result.callsign) {