Libraries: High-Performance Time Functions (TimeUtils) - page 3

 
Really good to use and Good job.
 
Supreb. Allways hating working with date and time variables.. This makes it so much easier!! Thanks
 

Is there a way to identify the 4th Thursday of November as it approaches each year using this library?

To be clear, I'm trying to get the U.S. Thanksgiving holiday date in advance of its arrival but it's a moving target in terms of its date.

Although trading is allowed in the U.S. on Thanksgiving, I would like to filter it out x days in advance and y days after.

 
Ryan L Johnson #:

Is there a way to identify the 4th Thursday of November as it approaches each year using this library?

To be clear, I'm trying to get the U.S. Thanksgiving holiday date in advance of its arrival but it's a moving target in terms of its date.

Although trading is allowed in the U.S. on Thanksgiving, I would like to filter it out x days in advance and y days after.

Please disregard the above. I found the holiday listed in MQ's U.S. Calendar even though it's not an FX market holiday in the U.S. Will access from there.

Thanks anyway. Nice library.

 
Ryan L Johnson #:

Is there a way to identify the 4th Thursday of November as it approaches each year using this library?

To be clear, I'm trying to get the U.S. Thanksgiving holiday date in advance of its arrival but it's a moving target in terms of its date.

Although trading is allowed in the U.S. on Thanksgiving, I would like to filter it out x days in advance and y days after.

This:

void OnStart()
  {
   // Code for the current year
   int currYear = GetYear(TimeCurrent());

   datetime Nov4thThurs = GetNthWeekdayInYearMonth(currYear, 11, 4, THURSDAY);
   //string formatted = TimeToString(Nov4thThurs, TIME_DATE);
   string formatted = TimeFormat(Nov4thThurs, "DDD, DD/MM/YYYY");
   Print(formatted);

   // Code for 10 years
   for(int y = 2020; y < 2030; y++)
     {
      Nov4thThurs = GetNthWeekdayInYearMonth(y, 11, 4, THURSDAY);
      string formatted = TimeFormat(Nov4thThurs, "DDDD, D MMMM YYYY");
      Print(formatted);
     }

  }

Result:

/*
  Thu, 24/11/2022
  Thursday, 26 November 2020
  Thursday, 25 November 2021
  Thursday, 24 November 2022
  Thursday, 23 November 2023
  Thursday, 28 November 2024
  Thursday, 27 November 2025
  Thursday, 26 November 2026
  Thursday, 25 November 2027
  Thursday, 23 November 2028
  Thursday, 22 November 2029

*/

 
Update 6 July 2026 - version 2.00

  • New March-based conversion routines derived from the Neri–Schneider calendar algorithm (here) + validation script.
  • Removed "performance" mode.
 

Update 18 July 2026 - version 2.50

  • Added AddPeriod() and SubPeriod() for calendar period arithmetic.
  • Added WithXxx() functions for replacing individual date/time fields.
  • Added IsInSession() overloads for checking recurring daily sessions.

//+==================================================================+
//| Session() Checks                                                 |
//+==================================================================+
bool IsInSession(datetime t,
                 int startHour,
                 int startMinute,
                 int endHour,
                 int endMinute);

bool IsInSession(int startHour,
                 int startMinute,
                 int endHour,
                 int endMinute);     // Uses TimeTradeServer()

bool IsInSession(string startTime,
                 string endTime);

To trade only during the London session (08:00-17:00).

// London session (08:00 -> 17:00 server time)
if(IsInSession(8, 0, 17, 0))
  {
   // Trading logic...
  }

Or, if you prefer using strings:

if(IsInSession("8:00", "17:00"))
  {
   // Trading logic...
  }

For sessions spanning midnight (like, the Asian session):

// Asian session (22:00 -> 06:00 server time)
if(IsInSession("22:00", "06:00"))
  {
   // Trading logic...
  }

 

Update 21 July 2026 - version 2.60

    Added comprehensive Trading Sessions and Economic Calendar utilities:
    • IsInSession()
    • IsInMarketSession()
    • IsSessionOverlap()
    • CurrentMarketSession()
    • MarketSessionName()
    • IsNearNews()
    • TimeUntilNews(), 
    General code cleanup and documentation improvements.

     
    A faster way to calculate the day-of-the-week
    A faster way to calculate the day-of-the-week
    • Ben Joffe
    • www.benjoffe.com
    A range of fast modulus techniques that beat compiler output
     

    I asked ChatGPT to analyze the article and write a benchmark script.

    The benchmark will test my current implementation vs Joffe's artilcle optimized methods.

    ChatGPT suggested another possible optimization in MQL5 is worth trying, also (combined implementation method #3).

    The "DayOfWeekBenchmark.mq5" script is attached below.

    //+------------------------------------------------------------------+
    //| Reference implementation                                         |
    //| Day of the week as integer (0 = Sunday to 6 = Saturday)          |
    //+------------------------------------------------------------------+
    int DayOfWeek_Current(const datetime t)
    {
       return (int)((t / DAYSECS + 4) % 7U);  // 1 Jan 1970 is Thursday
    }
    
    //+------------------------------------------------------------------+
    //| Combined implementation (Method 3)                               |
    //| Day of the week as integer (0 = Sunday to 6 = Saturday)          |
    //+------------------------------------------------------------------+
    int DayOfWeek_Combined(const datetime t)
    {
       return (int)((((ulong)t % WEEKSECS) / DAYSECS + 4) % 7ULL);   
    }
    

    Here are the results:
    /*
     ============================================================
     PERFORMANCE BENCHMARK
     ============================================================
     Times are measured with GetMicrosecondCount().
     Lower ns/call is better.
      
     Current                       best=      2425 us  avg=  2530.200 us  best=      2.42 ns/call  checksum=4
     Reciprocal                    best=      2266 us  avg=  2300.600 us  best=      2.27 ns/call  checksum=4
     Combined                      best=      1788 us  avg=  1810.800 us  best=      1.79 ns/call  checksum=4
     Joffe Narrow                  best=      1553 us  avg=  1635.900 us  best=      1.55 ns/call  checksum=4
     Joffe V3                      best=      1986 us  avg=  2005.700 us  best=      1.99 ns/call  checksum=4
      
     ============================================================
     RELATIVE PERFORMANCE
     ============================================================
     Current                       relative=   1.000x  speedup=   1.000x
     Reciprocal                    relative=   0.934x  speedup=   1.070x
     Combined                      relative=   0.737x  speedup=   1.356x
     Joffe Narrow                  relative=   0.640x  speedup=   1.561x
     Joffe V3                      relative=   0.819x  speedup=   1.221x
      
     ============================================================
     SUMMARY
     ============================================================
     Current     : original expression
     Reciprocal  : replaces /86400 with fixed-point multiplication
     Combined    : reduces seconds modulo one week first
     Joffe Narrow: 32-bit day-count multiply/add/shift
     Joffe V3    : 32-bit day-count high+low multiplication method
    
    */
    


    Edited:

    I used a similar technique to Joffey’s methods in my random number generator: Xoshiro256.mqh.

    This is particularly useful for a random number generator, where the bound function can be called millions of times.

    For the DayOfWeek() function, however, applying this optimization would be more of an overkill, given how infrequently the operation is typically performed.

    The technique replaces modulus division ( % ) with reciprocal multiplication, followed by right-shift and a correction step.

    Joffe's found the optimal reciprocal and correction for modulus 7, plus some other micro-optimizations.

    uint Xoshiro256::boundedUInt32(const uint bound)
      {
       ulong product = nextUInt32() * (ulong)bound;
       uint lo = (uint)product;
       if(lo < bound)
         {
          const uint t = (0u-bound) % bound;
          while(lo < t)
            {
             product = nextUInt32() * (ulong)bound;
             lo = (uint)product;
            }
         }
       return (uint) (product >> 32);
      }
    
    Files: