Libraries: Local Timezones and Local Session Hours - page 6

 
looks good
 

. New Time Zones Added:

  • Expanded ENUM_ZONE_ID to include 14 new time zones: US_NEWYORK , GB_LONDON , JP_TOKYO , AU_SYDNEY , HK_HONGKONG , DE_FRANKFURT , SG_SINGAPORE , CH_ZURICH , CA_TORONTO , AE_DUBAI , FR_PARIS , CN_SHANGHAI , RU_MOSCOW , IN_MUMBAI , ZA_JOHANNESBURG , ES_MADRID , NL_AMSTERDAM , KR_SEOUL , and MX_MEXICOCITY .
  • Updated m_tbl_city_names , m_tbl_utc_offset , m_tbl_dst_start , and m_tbl_dst_end arrays to accommodate the new time zones.

2. Daylight Saving Time (DST) Rules Implemented:

  • Added DST rules to GetDaylightSwitchTimes for: AU_SYDNEY , DE_FRANKFURT , GB_LONDON , US_NEWYORK , CH_ZURICH , CA_TORONTO , FR_PARIS , ES_MADRID , NL_AMSTERDAM , and MX_MEXICOCITY .
  • Explicitly defined "no DST" cases in GetDaylightSwitchTimes for: JP_TOKYO , ZONE_ID_UTC , HK_HONGKONG , SG_SINGAPORE , AE_DUBAI , CN_SHANGHAI , RU_MOSCOW , IN_MUMBAI , ZA_JOHANNESBURG , and KR_SEOUL .
Files:
TimeZoneInfo.mqh  135 kb
 
Kulara Baimurzina #:

. New Time Zones Added:

Thank you for the additions. This can be useful to adjust you trading times with local sessions of a stock market (e.g., Mumbai).
 

Very helpful code, thanks!

I did notice a bug with SessionHours.mqh:

If you set your session time goes over midnight (i.e. end hour is before start hour), the session is never considered open. e.g:

CSessionHours session(ZONE_ID_NEWYORK);
session.BeginLocalTime(22, 0);
session.EndLocalTime(0, 0);

session.SecRemainingSession() would always return 0, and
session.CheckLocalSession() would always return false

Edit:

This may be only in specific scenarios. I notice this issue when I'm running the tester, but when attaching to a chart the issue seems to be gone.

 

Subject: Regarding your code - TimeZoneInfo.mqh - minor adjustments

Hi amrali  ,

I wanted to reach out and say thank you for sharing your TimeZoneInfo.mqh . I found the code to be very well-structured and easy to understand, which made it a pleasure to work with.

I made a few minor adjustments to suit my specific needs, and it was straightforward due to the clear organization of your code.

However, I noticed a small issue when I was renaming your named constants. I inadvertently missed adding the "ZONE_ID_" prefix to some of them. As a result, those constants are now hardcoded, which isn't ideal.

To correct this, I've made the necessary changes and have attached the updated file, "TimeZoneInfo.mqh", to this message.

Again, I appreciate you sharing your work. It's a great example of well-written MQL5 code.

Thanks,

 
csol007 #:

Very helpful code, thanks!

I did notice a bug with SessionHours.mqh:

If you set your session time goes over midnight (i.e. end hour is before start hour), the session is never considered open. e.g:

You missed that session times are local Forex times in that city which usually starts with banks at 7-9 am to 5-6 pm. (i.e., hour 17-18 ).

So, it is not logical that the bank / local Forex session starts at or before midnight. 
 
amrali #:
You missed that session times are local Forex times in that city which usually starts with banks at 7-9 am to 5-6 pm. (i.e., hour 17-18 ).

So, it is not logical that the bank / local Forex session starts at or before midnight. 

I do understand the logic behind that, however, in my situation using the local timezone (Tokyo in this case) would add problems with DST (Tokyo doesn't use it, but NY does - which is the base timezone for the sessions I'm using). I also noticed an added complicate in that this morning's session (20:00 - 00:00 NY Time) is detected as a Sunday (since it is Sunday in that timezone, even though the local (Tokyo) time is Monday.

So I modified your session code this morning and:

  • Added a boolean to either use UTC or Localtime for SecRemainingSession() and CheckLocalSession()
  • When setting the Begin/EndLocalTime() it also stores the time in UTC
  • EndLocalTime() also checks that m_endlocaltime > m_beginlocaltime, and if not then moves it on one day
  • SecRemainingSession() and CheckLocalSession() will now check and compare the UTC times instead of localtime if m_useutctime is set to true

I haven't thoroughly checked whether converting to UTC will add problems, guess we'll see in the summer :)

Files:
 
csol007 #:


I do understand the logic behind that, however, in my situation using the local timezone (Tokyo in this case) would add problems with DST (Tokyo doesn't use it, but NY does - which is the base timezone for the sessions I'm using). I also noticed an added complicate in that this morning's session (20:00 - 00:00 NY Time) is detected as a Sunday (since it is Sunday in that timezone, even though the local (Tokyo) time is Monday.

A trading session is when the market is most active, so when the greatest volume of trades occur at one time. It is not when the forex market begins trading in that city.

It seems that you wrongly use NY session object, and try to deduct Tokyo session time from it. This is wrong as it should give the above error.

The local time in NY object was 20:00 Sunday, which maps to = 20:00 (NY_TIME) - (-5) NY_GMT_OFF + 9 (TOK_UTC_OFFSET) = 09:00 am Monday in Tokyo. 

Time in NY object is Sunday which is a weekend, although it 's Monday in Tokyo. This is exactly the same error you gave got.

The correct way to do it, is by directly using a [Tokyo session object] and leave the default start and end time at their default values (8 am - 5 pm).

CSessionHours tokyo(ZONE_ID_TOKYO);

void OnTick()
  {
   tokyo.RefreshTime();

   string str = StringFormat("Tokyo time: %s, Tokyo session is %s", 
                             tokyo.ToString(), 
                             tokyo.CheckLocalSession() ? "OPEN" : "CLOSED");
   Comment(str);   
  }

Please refer to Forex sessions in these links to understand time mappings in different major centres:

https://www.tradinghours.com/

https://forex.timezoneconverter.com/?timezone=GMT&refresh=5


Edit:

The aim of the library is to relieve the burden of time calculations off the user. If you want to use utc time and add offsets and dst then you don't need the library unless you do it right.

Each object in CsessionHours is pre-configured with the correct UTC offset and dst schedule, so you'll have to rework all of these stuff yourself. 
 

csol007 #:

If you set your session time goes over midnight (i.e. end hour is before start hour), the session is never considered open. e.g:

CSessionHours session(ZONE_ID_NEWYORK);
session.BeginLocalTime(22, 0);
session.EndLocalTime(0, 0);

To help understand the logic behind the session objects library, you can think of each type of object (depending on its ZONE_ID_xxx)  as a wall clock like in this picture. To know if Tokyo session is open simply look at the Tokyo clock (object). That's more natural/ direct way of thinking about it.


 
Kulara Baimurzina #:

Subject: Regarding your code - TimeZoneInfo.mqh - minor adjustments

I made a few minor adjustments to suit my specific needs, and it was straightforward due to the clear organization of your code.

However, I noticed a small issue when I was renaming your named constants. I inadvertently missed adding the "ZONE_ID_" prefix to some of them. As a result, those constants are now hardcoded, which isn't ideal.

To correct this, I've made the necessary changes and have attached the updated file, "TimeZoneInfo.mqh", to this message.

It would be much easier for you to configure the built-in custom timezone for the desired target location, instead of re-writing the library code, which is prone to errors and requires more time and effort as you did.

A demo to create a custom timezone, for example Dubai.

#include "TimeZoneInfo.mqh"

void OnStart()
  {
   // Configure the built-in custom timezone for Dubai timezone.
   // Duabi is GMT +4 hours. DST isn't applied.
   CTimeZoneInfo::SetCustomTimeZone("Dubai", 4*3600);

   // Now, Duabi timezone is accessible to all class methods via 'ZONE_ID_CUSTOM'
   CTimeZoneInfo tz(ZONE_ID_CUSTOM);

   // Get current time and other timezone information in Dubai
   Print("Name()                : ", tz.Name());
   Print("TimeUTC()             : ", tz.TimeUTC());
   Print("TimeLocal()           : ", tz.TimeLocal());
   Print("TimeGMTOffset()       : ", tz.TimeGMTOffset());
   Print("TimeDaylightSavings() : ", tz.TimeDaylightSavings());
   Print("ToString()            : ", tz.ToString());
  }

Output:

// Name()                : Dubai
// TimeUTC()             : 2025.02.24 20:41:43
// TimeLocal()           : 2025.02.25 00:41:43
// TimeGMTOffset()       : 14400
// TimeDaylightSavings() : 0
// ToString()            : Tue, 2025.02.25 00:41:43 GMT+4 STD [Dubai]

You can repeat the same logic for the other cities as you did for: Hong Kong, Singapore, Zurich, Toronto, Paris, Shanghai, Moscow, Mumbai, Johannesburg, Madrid, Amsterdam and Seoul.\

However, there is only ONE custom tz active at a time, the one in which you're interested.