Time Shield Library
C++ library for working with time
Loading...
Searching...
No Matches
time_zone_conversions.mqh
Go to the documentation of this file.
1//+------------------------------------------------------------------+
2//| time_zone_conversions.mqh |
3//| Time Shield - MQL5 Time Zone Conversions |
4//| Copyright 2025, NewYaroslav |
5//| https://github.com/NewYaroslav/time-shield-cpp |
6//+------------------------------------------------------------------+
7#ifndef __TIME_SHIELD_TIME_ZONE_CONVERSIONS_MQH__
8#define __TIME_SHIELD_TIME_ZONE_CONVERSIONS_MQH__
9
13
14#property copyright "Copyright 2025, NewYaroslav"
15#property link "https://github.com/NewYaroslav/time-shield-cpp"
16#property strict
17
18#include "time_conversions.mqh"
19
20namespace time_shield {
21
22 datetime zone_to_gmt(const datetime local, const TimeZone zone);
23 datetime gmt_to_zone(const datetime gmt, const TimeZone zone);
24
25 datetime cet_to_gmt_impl(const datetime cet) {
27 int max_days = num_days_in_month(dt.year, dt.mon);
28 const int OLD_START_SUMMER_HOUR = 2;
29 const int OLD_STOP_SUMMER_HOUR = 3;
30 const int NEW_SUMMER_HOUR = 1;
31
32 if(dt.year < 2002) {
33 if(dt.mon > MAR && dt.mon < OCT) {
34 return cet - (datetime)SEC_PER_HOUR * 2;
35 } else if(dt.mon == MAR) {
36 for(int d = max_days; d >= dt.day; --d) {
37 if(day_of_week_date(dt.year, MAR, d) == SUN) {
38 if(d == dt.day) {
39 if(dt.hour >= OLD_START_SUMMER_HOUR) {
40 return cet - (datetime)SEC_PER_HOUR * 2;
41 }
42 return cet - (datetime)SEC_PER_HOUR;
43 }
44 return cet - (datetime)SEC_PER_HOUR;
45 }
46 }
47 return cet - (datetime)SEC_PER_HOUR * 2;
48 } else if(dt.mon == OCT) {
49 for(int d = max_days; d >= dt.day; --d) {
50 if(day_of_week_date(dt.year, OCT, d) == SUN) {
51 if(d == dt.day) {
52 if(dt.hour >= OLD_STOP_SUMMER_HOUR) {
53 return cet - (datetime)SEC_PER_HOUR;
54 }
55 return cet - (datetime)SEC_PER_HOUR;
56 }
57 return cet - (datetime)SEC_PER_HOUR * 2;
58 }
59 }
60 return cet - (datetime)SEC_PER_HOUR;
61 }
62 return cet - (datetime)SEC_PER_HOUR;
63 }
64
65 if(dt.mon > MAR && dt.mon < OCT) {
66 return cet - (datetime)SEC_PER_HOUR * 2;
67 }
68 if(dt.mon == MAR) {
69 for(int d = max_days; d >= dt.day; --d) {
70 if(day_of_week_date(dt.year, MAR, d) == SUN) {
71 if(d == dt.day) {
72 if(dt.hour >= (NEW_SUMMER_HOUR + 2)) {
73 return cet - (datetime)SEC_PER_HOUR * 2;
74 }
75 return cet - (datetime)SEC_PER_HOUR;
76 }
77 return cet - (datetime)SEC_PER_HOUR;
78 }
79 }
80 return cet - (datetime)SEC_PER_HOUR * 2;
81 }
82 if(dt.mon == OCT) {
83 for(int d = max_days; d >= dt.day; --d) {
84 if(day_of_week_date(dt.year, OCT, d) == SUN) {
85 if(d == dt.day) {
86 if(dt.hour >= (NEW_SUMMER_HOUR + 1)) {
87 return cet - (datetime)SEC_PER_HOUR;
88 }
89 return cet - (datetime)SEC_PER_HOUR * 2;
90 }
91 return cet - (datetime)SEC_PER_HOUR * 2;
92 }
93 }
94 }
95 return cet - (datetime)SEC_PER_HOUR;
96 }
97
98 datetime gmt_to_cet_impl(const datetime gmt) {
100 const int SWITCH_HOUR = 1;
101
102 if(dt.mon > MAR && dt.mon < OCT) {
103 return gmt + (datetime)SEC_PER_HOUR * 2;
104 }
105 if(dt.mon == MAR) {
106 int last = last_sunday_month_day(dt.year, MAR);
107 if(dt.day > last) {
108 return gmt + (datetime)SEC_PER_HOUR * 2;
109 }
110 if(dt.day < last) {
111 return gmt + (datetime)SEC_PER_HOUR;
112 }
113 if(dt.hour >= SWITCH_HOUR) {
114 return gmt + (datetime)SEC_PER_HOUR * 2;
115 }
116 return gmt + (datetime)SEC_PER_HOUR;
117 }
118 if(dt.mon == OCT) {
119 int last = last_sunday_month_day(dt.year, OCT);
120 if(dt.day > last) {
121 return gmt + (datetime)SEC_PER_HOUR;
122 }
123 if(dt.day < last) {
124 return gmt + (datetime)SEC_PER_HOUR * 2;
125 }
126 if(dt.hour >= SWITCH_HOUR) {
127 return gmt + (datetime)SEC_PER_HOUR;
128 }
129 return gmt + (datetime)SEC_PER_HOUR * 2;
130 }
131 return gmt + (datetime)SEC_PER_HOUR;
132 }
133
134 datetime european_local_to_gmt(const datetime local, const int standard_offset_hours) {
135 return cet_to_gmt_impl(local - (datetime)SEC_PER_HOUR * (standard_offset_hours - 1));
136 }
137
138 datetime gmt_to_european_local(const datetime gmt, const int standard_offset_hours) {
139 return gmt_to_cet_impl(gmt) + (datetime)SEC_PER_HOUR * (standard_offset_hours - 1);
140 }
141
142 bool is_us_eastern_dst_local(const DateTimeStruct &dt) {
143 const int SWITCH_HOUR = 2;
144 int start_day = 0;
145 int end_day = 0;
146 int start_month = 0;
147 int end_month = 0;
148
149 if(dt.year >= 2007) {
150 start_month = MAR;
151 end_month = NOV;
152 int first_sunday_march =
153 1 + (DAYS_PER_WEEK - day_of_week_date(dt.year, MAR, 1)) % DAYS_PER_WEEK;
154 start_day = first_sunday_march + 7;
155 end_day =
156 1 + (DAYS_PER_WEEK - day_of_week_date(dt.year, NOV, 1)) % DAYS_PER_WEEK;
157 } else {
158 start_month = APR;
159 end_month = OCT;
160 start_day =
161 1 + (DAYS_PER_WEEK - day_of_week_date(dt.year, APR, 1)) % DAYS_PER_WEEK;
162 end_day = last_sunday_month_day(dt.year, OCT);
163 }
164
165 if(dt.mon > start_month && dt.mon < end_month) {
166 return true;
167 }
168 if(dt.mon < start_month || dt.mon > end_month) {
169 return false;
170 }
171 if(dt.mon == start_month) {
172 if(dt.day > start_day) {
173 return true;
174 }
175 if(dt.day < start_day) {
176 return false;
177 }
178 return dt.hour >= SWITCH_HOUR;
179 }
180 if(dt.mon == end_month) {
181 if(dt.day < end_day) {
182 return true;
183 }
184 if(dt.day > end_day) {
185 return false;
186 }
187 return dt.hour < SWITCH_HOUR;
188 }
189 return false;
190 }
191
192 bool fixed_zone_offset(const TimeZone zone, long &utc_offset) {
193 switch(zone) {
194 case GMT:
195 case UTC:
196 case WET:
197 utc_offset = 0;
198 return true;
199 case WEST:
200 utc_offset = SEC_PER_HOUR;
201 return true;
202 case CET:
203 utc_offset = SEC_PER_HOUR;
204 return true;
205 case CEST:
206 utc_offset = SEC_PER_HOUR * 2;
207 return true;
208 case EET:
209 utc_offset = SEC_PER_HOUR * 2;
210 return true;
211 case EEST:
212 utc_offset = SEC_PER_HOUR * 3;
213 return true;
214 case IST:
215 utc_offset = SEC_PER_HOUR * 5 + SEC_PER_MIN * 30;
216 return true;
217 case MYT:
218 case WITA:
219 case SGT:
220 case PHT:
221 case HKT:
222 utc_offset = SEC_PER_HOUR * 8;
223 return true;
224 case WIB:
225 case ICT:
226 utc_offset = SEC_PER_HOUR * 7;
227 return true;
228 case WIT:
229 case JST:
230 case KST:
231 utc_offset = SEC_PER_HOUR * 9;
232 return true;
233 case KZT:
234 utc_offset = SEC_PER_HOUR * 5;
235 return true;
236 case TRT:
237 case BYT:
238 utc_offset = SEC_PER_HOUR * 3;
239 return true;
240 case GST:
241 utc_offset = SEC_PER_HOUR * 4;
242 return true;
243 default:
244 utc_offset = 0;
245 return false;
246 }
247 }
248
251 datetime cet_to_gmt(const datetime cet) {
252 return cet_to_gmt_impl(cet);
253 }
254
257 datetime eet_to_gmt(const datetime eet) {
258 return european_local_to_gmt(eet, 2);
259 }
260
263 datetime gmt_to_cet(const datetime gmt) {
264 return gmt_to_cet_impl(gmt);
265 }
266
269 datetime gmt_to_eet(const datetime gmt) {
270 return gmt_to_european_local(gmt, 2);
271 }
272
275 datetime et_to_gmt(const datetime et) {
277 bool is_dst = is_us_eastern_dst_local(dt);
278 return et + (datetime)SEC_PER_HOUR * (is_dst ? 4 : 5);
279 }
280
283 datetime gmt_to_et(const datetime gmt) {
284 datetime et_standard = gmt - (datetime)SEC_PER_HOUR * 5;
285 DateTimeStruct dt_local = to_date_time(et_standard);
286 bool is_dst = is_us_eastern_dst_local(dt_local);
287 return gmt - (datetime)SEC_PER_HOUR * (is_dst ? 4 : 5);
288 }
289
292 datetime ny_to_gmt(const datetime ny) {
293 return et_to_gmt(ny);
294 }
295
298 datetime gmt_to_ny(const datetime gmt) {
299 return gmt_to_et(gmt);
300 }
301
304 datetime ct_to_gmt(const datetime ct) {
305 return et_to_gmt(ct + (datetime)SEC_PER_HOUR);
306 }
307
310 datetime gmt_to_ct(const datetime gmt) {
311 return gmt_to_et(gmt) - (datetime)SEC_PER_HOUR;
312 }
313
316 datetime zone_to_gmt(const datetime local, const TimeZone zone) {
317 if(local == (datetime)ERROR_TIMESTAMP) {
318 return (datetime)ERROR_TIMESTAMP;
319 }
320
321 long utc_offset = 0;
322 switch(zone) {
323 case GMT:
324 case UTC:
325 return local;
326 case WET:
327 return european_local_to_gmt(local, 0);
328 case CET:
329 return cet_to_gmt(local);
330 case EET:
331 return eet_to_gmt(local);
332 case WEST:
333 case CEST:
334 case EEST:
335 fixed_zone_offset(zone, utc_offset);
336 return local - (datetime)utc_offset;
337 case ET:
338 return et_to_gmt(local);
339 case CT:
340 return ct_to_gmt(local);
341 case UNKNOWN:
342 return (datetime)ERROR_TIMESTAMP;
343 default:
344 if(fixed_zone_offset(zone, utc_offset)) {
345 return local - (datetime)utc_offset;
346 }
347 return (datetime)ERROR_TIMESTAMP;
348 }
349 }
350
353 datetime gmt_to_zone(const datetime gmt, const TimeZone zone) {
354 if(gmt == (datetime)ERROR_TIMESTAMP) {
355 return (datetime)ERROR_TIMESTAMP;
356 }
357
358 long utc_offset = 0;
359 switch(zone) {
360 case GMT:
361 case UTC:
362 return gmt;
363 case WET:
364 return gmt_to_european_local(gmt, 0);
365 case CET:
366 return gmt_to_cet(gmt);
367 case EET:
368 return gmt_to_eet(gmt);
369 case WEST:
370 case CEST:
371 case EEST:
372 fixed_zone_offset(zone, utc_offset);
373 return gmt + (datetime)utc_offset;
374 case ET:
375 return gmt_to_et(gmt);
376 case CT:
377 return gmt_to_ct(gmt);
378 case UNKNOWN:
379 return (datetime)ERROR_TIMESTAMP;
380 default:
381 if(fixed_zone_offset(zone, utc_offset)) {
382 return gmt + (datetime)utc_offset;
383 }
384 return (datetime)ERROR_TIMESTAMP;
385 }
386 }
387
390 datetime convert_time_zone(const datetime local, const TimeZone from, const TimeZone to) {
391 datetime gmt = zone_to_gmt(local, from);
392 if(gmt == (datetime)ERROR_TIMESTAMP) {
393 return (datetime)ERROR_TIMESTAMP;
394 }
395 return gmt_to_zone(gmt, to);
396 }
397
398 datetime ist_to_gmt(const datetime ist) { return zone_to_gmt(ist, IST); }
399 datetime gmt_to_ist(const datetime gmt) { return gmt_to_zone(gmt, IST); }
400
401 datetime myt_to_gmt(const datetime myt) { return zone_to_gmt(myt, MYT); }
402 datetime gmt_to_myt(const datetime gmt) { return gmt_to_zone(gmt, MYT); }
403
404 datetime wib_to_gmt(const datetime wib) { return zone_to_gmt(wib, WIB); }
405 datetime gmt_to_wib(const datetime gmt) { return gmt_to_zone(gmt, WIB); }
406
407 datetime wita_to_gmt(const datetime wita) { return zone_to_gmt(wita, WITA); }
408 datetime gmt_to_wita(const datetime gmt) { return gmt_to_zone(gmt, WITA); }
409
410 datetime wit_to_gmt(const datetime wit) { return zone_to_gmt(wit, WIT); }
411 datetime gmt_to_wit(const datetime gmt) { return gmt_to_zone(gmt, WIT); }
412
413 datetime kzt_to_gmt(const datetime kzt) { return zone_to_gmt(kzt, KZT); }
414 datetime gmt_to_kzt(const datetime gmt) { return gmt_to_zone(gmt, KZT); }
415
416 datetime trt_to_gmt(const datetime trt) { return zone_to_gmt(trt, TRT); }
417 datetime gmt_to_trt(const datetime gmt) { return gmt_to_zone(gmt, TRT); }
418
419 datetime byt_to_gmt(const datetime byt) { return zone_to_gmt(byt, BYT); }
420 datetime gmt_to_byt(const datetime gmt) { return gmt_to_zone(gmt, BYT); }
421
422 datetime sgt_to_gmt(const datetime sgt) { return zone_to_gmt(sgt, SGT); }
423 datetime gmt_to_sgt(const datetime gmt) { return gmt_to_zone(gmt, SGT); }
424
425 datetime ict_to_gmt(const datetime ict) { return zone_to_gmt(ict, ICT); }
426 datetime gmt_to_ict(const datetime gmt) { return gmt_to_zone(gmt, ICT); }
427
428 datetime pht_to_gmt(const datetime pht) { return zone_to_gmt(pht, PHT); }
429 datetime gmt_to_pht(const datetime gmt) { return gmt_to_zone(gmt, PHT); }
430
431 datetime gst_to_gmt(const datetime gst) { return zone_to_gmt(gst, GST); }
432 datetime gmt_to_gst(const datetime gmt) { return gmt_to_zone(gmt, GST); }
433
434 datetime hkt_to_gmt(const datetime hkt) { return zone_to_gmt(hkt, HKT); }
435 datetime gmt_to_hkt(const datetime gmt) { return gmt_to_zone(gmt, HKT); }
436
437 datetime jst_to_gmt(const datetime jst) { return zone_to_gmt(jst, JST); }
438 datetime gmt_to_jst(const datetime gmt) { return gmt_to_zone(gmt, JST); }
439
440 datetime kst_to_gmt(const datetime kst) { return zone_to_gmt(kst, KST); }
441 datetime gmt_to_kst(const datetime gmt) { return gmt_to_zone(gmt, KST); }
442
443 datetime kyiv_to_gmt(const datetime kyiv) { return eet_to_gmt(kyiv); }
444 datetime gmt_to_kyiv(const datetime gmt) { return gmt_to_eet(gmt); }
445
446}; // namespace time_shield
447
448#endif // __TIME_SHIELD_TIME_ZONE_CONVERSIONS_MQH__
constexpr int64_t ERROR_TIMESTAMP
Error timestamp value.
constexpr int64_t DAYS_PER_WEEK
Days per week.
constexpr int64_t SEC_PER_HOUR
Seconds per hour.
constexpr int64_t SEC_PER_MIN
Seconds per minute.
ts_t gmt_to_et(ts_t gmt)
Convert GMT (UTC) to US Eastern Time (New York, EST/EDT).
ts_t kzt_to_gmt(ts_t kzt)
ts_t eet_to_gmt(ts_t eet)
Convert Eastern European Time to Greenwich Mean Time.
ts_t gmt_to_gst(ts_t gmt)
ts_t gmt_to_hkt(ts_t gmt)
ts_t gmt_to_eet(ts_t gmt)
Convert Greenwich Mean Time to Eastern European Time.
ts_t gst_to_gmt(ts_t gst)
ts_t byt_to_gmt(ts_t byt)
ts_t gmt_to_kyiv(ts_t gmt)
Convert GMT to Kyiv civil time using the EET/EEST rules.
ts_t gmt_to_ist(ts_t gmt)
ts_t ct_to_gmt(ts_t ct)
Convert US Central Time (America/Chicago, CST/CDT) to GMT (UTC).
ts_t gmt_to_jst(ts_t gmt)
bool is_us_eastern_dst_local(const DateTimeStruct &dt)
Check if local US Eastern time uses DST.
ts_t ict_to_gmt(ts_t ict)
ts_t gmt_to_wit(ts_t gmt)
ts_t gmt_to_kzt(ts_t gmt)
ts_t kyiv_to_gmt(ts_t kyiv)
Convert Kyiv civil time to GMT using the EET/EEST rules.
ts_t wita_to_gmt(ts_t wita)
ts_t cet_to_gmt(ts_t cet)
Convert Central European Time to Greenwich Mean Time.
ts_t convert_time_zone(ts_t local, TimeZone from, TimeZone to)
Convert a timestamp between two supported local civil time zones.
ts_t gmt_to_byt(ts_t gmt)
ts_t gmt_to_pht(ts_t gmt)
ts_t gmt_to_ny(ts_t gmt)
Convert GMT (UTC) to New York Time.
ts_t gmt_to_cet(ts_t gmt)
Convert Greenwich Mean Time to Central European Time.
ts_t gmt_to_sgt(ts_t gmt)
ts_t kst_to_gmt(ts_t kst)
ts_t gmt_to_trt(ts_t gmt)
ts_t zone_to_gmt(ts_t local, TimeZone zone)
Convert supported local civil time to GMT (UTC).
ts_t wit_to_gmt(ts_t wit)
ts_t hkt_to_gmt(ts_t hkt)
ts_t gmt_to_ict(ts_t gmt)
ts_t ist_to_gmt(ts_t ist)
ts_t gmt_to_wib(ts_t gmt)
ts_t gmt_to_myt(ts_t gmt)
ts_t wib_to_gmt(ts_t wib)
ts_t trt_to_gmt(ts_t trt)
ts_t gmt_to_zone(ts_t gmt, TimeZone zone)
Convert GMT (UTC) to a supported local civil time zone.
ts_t pht_to_gmt(ts_t pht)
ts_t sgt_to_gmt(ts_t sgt)
ts_t ny_to_gmt(ts_t ny)
Convert New York Time to GMT (UTC).
ts_t gmt_to_wita(ts_t gmt)
ts_t et_to_gmt(ts_t et)
Convert US Eastern Time (New York, EST/EDT) to GMT (UTC).
ts_t gmt_to_ct(ts_t gmt)
Convert GMT (UTC) to US Central Time (America/Chicago, CST/CDT).
ts_t gmt_to_kst(ts_t gmt)
ts_t jst_to_gmt(ts_t jst)
ts_t myt_to_gmt(ts_t myt)
TIME_SHIELD_CONSTEXPR T1 day_of_week_date(T2 year, T3 month, T4 day)
Get the day of the week.
@ OCT
October.
Definition enums.hpp:103
@ NOV
November.
Definition enums.hpp:104
@ MAR
March.
Definition enums.hpp:96
@ APR
April.
Definition enums.hpp:97
@ JST
Japan Standard Time.
Definition enums.hpp:200
@ GST
Gulf Standard Time.
Definition enums.hpp:198
@ PHT
Philippine Time.
Definition enums.hpp:197
@ BYT
Belarus Time.
Definition enums.hpp:194
@ KST
Korea Standard Time.
Definition enums.hpp:201
@ ET
US Eastern Time.
Definition enums.hpp:185
@ EET
Eastern European Time.
Definition enums.hpp:179
@ CEST
Central European Summer Time.
Definition enums.hpp:183
@ WIT
Eastern Indonesia Time.
Definition enums.hpp:191
@ WEST
Western European Summer Time.
Definition enums.hpp:184
@ WITA
Central Indonesia Time.
Definition enums.hpp:190
@ MYT
Malaysia Time.
Definition enums.hpp:188
@ HKT
Hong Kong Time.
Definition enums.hpp:199
@ WET
Western European Time.
Definition enums.hpp:181
@ KZT
Kazakhstan Time.
Definition enums.hpp:192
@ UNKNOWN
Unknown Time Zone.
Definition enums.hpp:202
@ TRT
Turkey Time.
Definition enums.hpp:193
@ UTC
Coordinated Universal Time.
Definition enums.hpp:178
@ ICT
Indochina Time.
Definition enums.hpp:196
@ GMT
Greenwich Mean Time.
Definition enums.hpp:177
@ SGT
Singapore Time.
Definition enums.hpp:195
@ WIB
Western Indonesia Time.
Definition enums.hpp:189
@ EEST
Eastern European Summer Time.
Definition enums.hpp:182
@ CT
US Central Time.
Definition enums.hpp:186
@ CET
Central European Time.
Definition enums.hpp:180
@ IST
India Standard Time.
Definition enums.hpp:187
@ SUN
Sunday.
Definition enums.hpp:28
TIME_SHIELD_CONSTEXPR T1 last_sunday_month_day(T2 year, T3 month)
Get the day of the last Sunday of the given month and year.
T1 to_date_time(T2 ts)
Converts a timestamp to a date-time structure.
TIME_SHIELD_CONSTEXPR T1 num_days_in_month(T2 year, T3 month) noexcept
Get the number of days in a month.
Main namespace for the Time Shield library.
bool fixed_zone_offset(const TimeZone zone, long &utc_offset)
datetime gmt_to_european_local(const datetime gmt, const int standard_offset_hours)
datetime gmt_to_cet_impl(const datetime gmt)
datetime european_local_to_gmt(const datetime local, const int standard_offset_hours)
datetime cet_to_gmt_impl(const datetime cet)
Structure to represent date and time.
int hour
Hour component of time (0-23).
int64_t year
Year component of the date.
int day
Day component of the date (1-31).
int mon
Month component of the date (1-12).
Header with helper functions for converting between different time representations in MQL5.