OpenCPN Partial API docs
Loading...
Searching...
No Matches
datetime.cpp
1/***************************************************************************
2 * Copyright (C) 2023 by David Register *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
18 **************************************************************************/
19
20#include <wx/tokenzr.h>
21#include <iomanip>
22#include <sstream>
23
24#include "model/datetime.h"
25#include "ocpn_plugin.h"
26
27#if wxCHECK_VERSION(3, 1, 6)
28#include <wx/uilocale.h>
29#endif
30
31#ifdef __ANDROID__
32#include "androidUTIL.h"
33#endif
34
35namespace ocpn {
36
37wxString getUsrDateTimeFormat() { return ::g_datetime_format; }
38
39// date/time in the desired time zone format.
40wxString toUsrDateTimeFormat(const wxDateTime date_time,
42#if wxCHECK_VERSION(3, 1, 6)
43 ,
44 const wxUILocale& locale
45#endif
46) {
47 wxDateTime t(date_time);
48 wxString effective_time_zone = options.time_zone;
49 if (effective_time_zone == wxEmptyString) {
50 effective_time_zone = ::g_datetime_format;
51 }
52 if (effective_time_zone == wxEmptyString) {
53 effective_time_zone = "UTC";
54 }
55#ifdef __ANDROID__
56 wxString aform = androidGetLocalizedDateTime(options, date_time);
57 if (!aform.IsEmpty()) return aform;
58#endif
59
60 // Define a map for custom format specifiers.
61 std::vector<std::pair<wxString, wxString>> formatMap = {
62#if wxCHECK_VERSION(3, 1, 6)
63 // Note: the GetInfo() method may return special unicode characters, such
64 // as narrow no-break space (U+202F).
65 {"$long_date_time", locale.GetInfo(wxLOCALE_LONG_DATE_FMT) + " " +
66 locale.GetInfo(wxLOCALE_TIME_FMT)},
67 {"$long_date", locale.GetInfo(wxLOCALE_LONG_DATE_FMT)},
68 {"$weekday_short_date_time", "%a " +
69 locale.GetInfo(wxLOCALE_SHORT_DATE_FMT) +
70 " " + locale.GetInfo(wxLOCALE_TIME_FMT)},
71 {"$weekday_short_date", "%a " + locale.GetInfo(wxLOCALE_SHORT_DATE_FMT)},
72 {"$short_date_time", locale.GetInfo(wxLOCALE_SHORT_DATE_FMT) + " " +
73 locale.GetInfo(wxLOCALE_TIME_FMT)},
74 {"$short_date", locale.GetInfo(wxLOCALE_SHORT_DATE_FMT)},
75 {"$hour_minutes_seconds", locale.GetInfo(wxLOCALE_TIME_FMT)},
76#else
77 {"$long_date_time", "%x %X"},
78 {"$long_date", "%x"}, // There is no descriptor for localized long date.
79 // Fallback to short date.
80 {"$weekday_short_date_time", "%a %x %X"},
81 {"$weekday_short_date", "%a %x"},
82 {"$short_date_time", "%x %X"},
83 {"$short_date", "%x"},
84 {"$hour_minutes_seconds", "%X"},
85#endif
86 {"$hour_minutes", "%H:%M"},
87 {"$24_hour_minutes_seconds", "%H:%M:%S"},
88 };
89 wxString format = options.format_string;
90 if (format == wxEmptyString) {
91 format = "$weekday_short_date_time";
92 }
93 // Iterate through the formatMap and replace each key with its value in
94 // the format string.
95 for (const auto& pair : formatMap) {
96 if (format.Contains(pair.first)) {
97 format.Replace(pair.first, pair.second);
98 }
99 }
100 // wxDateTime::Format() does not work when the format string contains 0x202F
101 // (narrow no-break space). Replace it with a regular space.
102 format.Replace(wxString(wxUniChar(0x202F)), " ");
103 wxString ret;
104 wxString tzName;
105 if (effective_time_zone == "Local Time") {
106 wxDateTime now = wxDateTime::Now();
107 if ((now == (now.ToGMT())) &&
108 t.IsDST()) // bug in wxWingets 3.0 for UTC meridien ?
109 t.Add(wxTimeSpan(1, 0, 0, 0));
110 if (options.show_timezone) {
111#ifdef __WXMSW__
112 tzName = _("LOC");
113#else
114 // Get the name of the timezone configured in the operating system.
115 // Formatting with the actual timezone (rather than "LOC") makes the
116 // labels unambiguous, even if the user changes the timezone settings in
117 // the operating system. For example "2021-10-31 01:30:00 EDT" is
118 // unambiguous, while "2021-10-31 01:30:00 LOC" is not.
119 tzName = t.Format("%Z");
120#endif
121 }
122 } else if (effective_time_zone == "LMT") {
123 // Local mean solar time at the current location.
124 t.MakeUTC();
125 tzName = _("LMT");
126 if (std::isnan(options.longitude)) {
127 t = wxInvalidDateTime;
128 } else {
129 t.Add(wxTimeSpan(0, 0, wxLongLong(options.longitude * 3600. / 15.)));
130 }
131 } else {
132 // UTC, or fallback to UTC if the timezone is not recognized.
133 t.MakeUTC();
134 tzName = _("UTC");
135 }
136 wxString formattedDate = t.Format(format);
137 if (options.show_timezone) {
138 return formattedDate + " " + tzName;
139 } else {
140 return formattedDate;
141 }
142}
143
144} // namespace ocpn
Standard, mostly strings utilities.
Definition datetime.cpp:35
wxString getUsrDateTimeFormat()
Return the date/time format to use when formatting date/time strings.
Definition datetime.cpp:37
PlugIn Object Definition/API.
Configuration options for date and time formatting.