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
31namespace ocpn {
32
33wxString getUsrDateTimeFormat() { return ::g_datetime_format; }
34
35// date/time in the desired time zone format.
36wxString toUsrDateTimeFormat(const wxDateTime date_time,
38#if wxCHECK_VERSION(3, 1, 6)
39 ,
40 const wxUILocale& locale
41#endif
42) {
43 wxDateTime t(date_time);
44 wxString effective_time_zone = options.time_zone;
45 if (effective_time_zone == wxEmptyString) {
46 effective_time_zone = ::g_datetime_format;
47 }
48 if (effective_time_zone == wxEmptyString) {
49 effective_time_zone = "UTC";
50 }
51 // Define a map for custom format specifiers.
52 std::vector<std::pair<wxString, wxString>> formatMap = {
53#if wxCHECK_VERSION(3, 1, 6)
54 // Note: the GetInfo() method may return special unicode characters, such
55 // as narrow no-break space (U+202F).
56 {"$long_date_time", locale.GetInfo(wxLOCALE_LONG_DATE_FMT) + " " +
57 locale.GetInfo(wxLOCALE_TIME_FMT)},
58 {"$long_date", locale.GetInfo(wxLOCALE_LONG_DATE_FMT)},
59 {"$weekday_short_date_time", "%a " +
60 locale.GetInfo(wxLOCALE_SHORT_DATE_FMT) +
61 " " + locale.GetInfo(wxLOCALE_TIME_FMT)},
62 {"$weekday_short_date", "%a " + locale.GetInfo(wxLOCALE_SHORT_DATE_FMT)},
63 {"short_date_time", locale.GetInfo(wxLOCALE_SHORT_DATE_FMT) + " " +
64 locale.GetInfo(wxLOCALE_TIME_FMT)},
65 {"$short_date", locale.GetInfo(wxLOCALE_SHORT_DATE_FMT)},
66 {"$hour_minutes_seconds", locale.GetInfo(wxLOCALE_TIME_FMT)},
67#else
68 {"$long_date_time", "%x %X"},
69 {"$long_date", "%x"}, // There is no descriptor for localized long date.
70 // Fallback to short date.
71 {"$weekday_short_date_time", "%a %x %X"},
72 {"$weekday_short_date", "%a %x"},
73 {"$short_date_time", "%x %X"},
74 {"$short_date", "%x"},
75 {"$hour_minutes_seconds", "%X"},
76#endif
77 {"$hour_minutes", "%H:%M"},
78 {"$24_hour_minutes_seconds", "%H:%M:%S"},
79 };
80 wxString format = options.format_string;
81 if (format == wxEmptyString) {
82 format = "$weekday_short_date_time";
83 }
84 // Iterate through the formatMap and replace each key with its value in
85 // the format string.
86 for (const auto& pair : formatMap) {
87 if (format.Contains(pair.first)) {
88 format.Replace(pair.first, pair.second);
89 }
90 }
91 // wxDateTime::Format() does not work when the format string contains 0x202F
92 // (narrow no-break space). Replace it with a regular space.
93 format.Replace(wxString(wxUniChar(0x202F)), " ");
94 wxString ret;
95 wxString tzName;
96 if (effective_time_zone == "Local Time") {
97 wxDateTime now = wxDateTime::Now();
98 if ((now == (now.ToGMT())) &&
99 t.IsDST()) // bug in wxWingets 3.0 for UTC meridien ?
100 t.Add(wxTimeSpan(1, 0, 0, 0));
101 if (options.show_timezone) {
102#ifdef __WXMSW__
103 tzName = _("LOC");
104#else
105 // Get the name of the timezone configured in the operating system.
106 // Formatting with the actual timezone (rather than "LOC") makes the
107 // labels unambiguous, even if the user changes the timezone settings in
108 // the operating system. For example "2021-10-31 01:30:00 EDT" is
109 // unambiguous, while "2021-10-31 01:30:00 LOC" is not.
110 tzName = t.Format("%Z");
111#endif
112 }
113 } else if (effective_time_zone == "LMT") {
114 // Local mean solar time at the current location.
115 t.MakeUTC();
116 tzName = _("LMT");
117 if (std::isnan(options.longitude)) {
118 t = wxInvalidDateTime;
119 } else {
120 t.Add(wxTimeSpan(0, 0, wxLongLong(options.longitude * 3600. / 15.)));
121 }
122 } else {
123 // UTC, or fallback to UTC if the timezone is not recognized.
124 t.MakeUTC();
125 tzName = _("UTC");
126 }
127 wxString formattedDate = t.Format(format);
128 if (options.show_timezone) {
129 return formattedDate + " " + tzName;
130 } else {
131 return formattedDate;
132 }
133}
134
135} // namespace ocpn
Standard, mostly strings utilities.
Definition datetime.cpp:31
wxString getUsrDateTimeFormat()
Return the date/time format to use when formatting date/time strings.
Definition datetime.cpp:33
PlugIn Object Definition/API.
Configuration options for date and time formatting.