2026-07-18 23:27:05 +03:00
//+------------------------------------------------------------------+
//| TimeUtils.mqh |
//| Copyright © 2026, Amr Ali |
//| https://www.mql5.com/en/users/amrali |
//+------------------------------------------------------------------+
# property copyright " Copyright © 2026, Amr Ali "
# property link " https://www.mql5.com/en/users/amrali "
2026-07-20 07:45:57 +03:00
# property version " 2.55 "
2026-07-18 23:27:05 +03:00
# property description " High-performance functions for dealing with time. "
// Updates:
2026-07-20 07:45:57 +03:00
// 2024.12.03 - v1.10 : Initial release.
// 2024.12.05 - v1.15 : Added functions for business days and for Nth() weekday of the month. Optimized calculations in DaysInMonth() function.
// 2024.12.09 - v1.20 : Added TimeFormat() function to format the time according to the passed string of tokens.
// 2024.12.09 - v1.25 : Optimized calculations in TimeToStructFast() function.
// 2024.12.10 - v1.30 : Optimized TimeFormat(), StartOfYear() and EndOfYear() functions. Updated descriptions of some functions.
// 2024.12.15 - v1.35 : Optimized NthWeekdayOfYearMonth() function.
// 2024.12.18 - v1.40 : Added IsCurrentXXX(), IsToday(), IsTomorrow() and IsYesterday() functions.
// 2024.12.19 - v1.45 : Optimized AddMonths() and NthWeekdayOfYearMonth() functions.
// 2024.12.20 - v1.50 : More code clean-up.
// 2024.12.21 - v1.55 : Simplified calculations in AddMonths(): replaced the complex logic of adjusting months and years with a simpler total months calculation.
// 2026.06.22 - v1.60 : Optimized AddBusinessDays() and DifferenceInBusinessDays() functions. Added various IsXXX() check functions.
// 2026.07.06 - v2.00 : New March-based conversion routines derived from the Neri–Schneider calendar algorithm + validation script. Removed "performance" mode.
// 2026.07.07 - v2.10 : Added DaysInYear(), LastDayOf(), MinuteOf(), HourOf() and CalendarDifferenceToString() functions.
// 2026.07.10 - v2.30 : Added date construction, quarter, calendar difference, and relative-date helper functions. Introduced configurable week start and renamed several functions for a cleaner, more consistent API.
// 2026.07.12 - v2.35 : Updated CalendarDifferenceToString() to return the precise elapsed time, including hours, minutes, and seconds.
// 2026.07.14 - v2.40 : Redesigned the year/month decomposition in CalendarDifferenceToString() to correctly handle February 29 edge cases. Simplified and optimized the DifferenceInXXX() functions. Added epoch-based index functions.
// 2026.07.15 - v2.45 : Added CalendarDifference() to return the calendar difference between two dates, broken down into years, months, days, hours, minutes, and seconds.
// 2026.07.18 - v2.50 : Added AddPeriod() and SubPeriod() for calendar period arithmetic. Added WithXxx() functions for replacing individual date/time fields. Added IsInSession() for checking recurring daily sessions.
// 2026.07.20 - v2.55 : Optimized week-based functions. Added SessionOverlap() for calculating overlapping time intervals. Improved documentation and API comments.
2026-07-18 23:27:05 +03:00
# ifdef __MQL4__
# property strict
# endif
# ifndef TIMEUTILS_UNIQUE_HEADER_ID_H
# define TIMEUTILS_UNIQUE_HEADER_ID_H
// First day of the week used by all week-related functions.
// Optionally, override the default before including this header:
//
// #define TIMEUTILS_FIRST_DAY_OF_WEEK SUNDAY
// #include "TimeUtils.mqh"
//
// Valid values: SUNDAY or MONDAY (default: MONDAY).
# ifndef TIMEUTILS_FIRST_DAY_OF_WEEK
# define TIMEUTILS_FIRST_DAY_OF_WEEK MONDAY
# endif
//####################################################################
//# #
2026-07-20 07:45:57 +03:00
//# Construction & Conversion #
2026-07-18 23:27:05 +03:00
//# #
//####################################################################
2026-07-20 07:45:57 +03:00
//DateFrom(2026, 7, 20)
//DateFromString("2026.07.20 14:30")
//TimeToStructFast(datetime, MqlDateTime)
//StructToTimeFast(MqlDateTime)
2026-07-18 23:27:05 +03:00
//####################################################################
//# #
2026-07-20 07:45:57 +03:00
//# Calendar Fields & Components #
2026-07-18 23:27:05 +03:00
//# #
//####################################################################
//+==================================================================+
2026-07-20 07:45:57 +03:00
//| Calendar Fields |
2026-07-18 23:27:05 +03:00
//+==================================================================+
2026-07-20 07:45:57 +03:00
// Year(datetime) Month(datetime)
// Day(datetime) Hour(datetime)
// Minute(datetime) Second(datetime)
2026-07-18 23:27:05 +03:00
2026-07-20 07:45:57 +03:00
// DayOfWeek(datetime) datetime DateOnly(tm)
// DayOfYear(datetime) datetime TimeOnly(tm)
2026-07-18 23:27:05 +03:00
2026-07-20 07:45:57 +03:00
//####################################################################
//# #
//# Calendar Indices & Positions #
//# #
//####################################################################
2026-07-18 23:27:05 +03:00
//+==================================================================+
2026-07-20 07:45:57 +03:00
//| Absolute Indices |
2026-07-18 23:27:05 +03:00
//+==================================================================+
2026-07-20 07:45:57 +03:00
// YearIndex(datetime) MonthIndex(datetime)
// QuarterIndex(datetime) WeekIndex(datetime)
// DayIndex(datetime) HourIndex(datetime)
// MinuteIndex(datetime)
2026-07-18 23:27:05 +03:00
//+==================================================================+
2026-07-20 07:45:57 +03:00
//| Position Within Calendar |
2026-07-18 23:27:05 +03:00
//+==================================================================+
2026-07-20 07:45:57 +03:00
// Quarter(datetime)
2026-07-18 23:27:05 +03:00
2026-07-20 07:45:57 +03:00
// WeekOfYear(datetime) WeekOfMonth(datetime)
2026-07-18 23:27:05 +03:00
2026-07-20 07:45:57 +03:00
// HourOfYear(datetime) MinuteOfYear(datetime)
// HourOfQuarter(datetime) MinuteOfQuarter(datetime)
// HourOfMonth(datetime) MinuteOfMonth(datetime)
// HourOfWeek(datetime) MinuteOfWeek(datetime)
// MinuteOfDay(datetime)
2026-07-18 23:27:05 +03:00
2026-07-20 07:45:57 +03:00
// SecsElapsedOfYear(datetime) SecsElapsedOfQuarter(datetime)
// SecsElapsedOfMonth(datetime) SecsElapsedOfWeek(datetime)
// SecsElapsedOfDay(datetime) SecsElapsedOfHour(datetime)
// SecsElapsedOfMinute(datetime) SecsElapsedOfEpoch(datetime)
2026-07-18 23:27:05 +03:00
2026-07-20 07:45:57 +03:00
// SecondsSinceMidnight(datetime)
2026-07-18 23:27:05 +03:00
//####################################################################
//# #
2026-07-20 07:45:57 +03:00
//# Navigation / Manipulation #
2026-07-18 23:27:05 +03:00
//# #
//####################################################################
//+==================================================================+
2026-07-20 07:45:57 +03:00
//| Period Boundaries |
2026-07-18 23:27:05 +03:00
//+==================================================================+
2026-07-20 07:45:57 +03:00
// datetime StartOfMinute(datetime) datetime EndOfMinute(datetime)
// datetime StartOfHour(datetime) datetime EndOfHour(datetime)
// datetime StartOfDay(datetime) datetime EndOfDay(datetime)
// datetime StartOfWeek(datetime) datetime EndOfWeek(datetime)
// datetime StartOfMonth(datetime) datetime EndOfMonth(datetime)
// datetime StartOfQuarter(datetime) datetime EndOfQuarter(datetime)
// datetime StartOfYear(datetime) datetime EndOfYear(datetime)
2026-07-18 23:27:05 +03:00
2026-07-20 07:45:57 +03:00
// datetime StartOfToday() datetime EndOfToday()
// datetime StartOfTomorrow() datetime EndOfTomorrow()
// datetime StartOfYesterday() datetime EndOfYesterday()
2026-07-18 23:27:05 +03:00
//+==================================================================+
2026-07-20 07:45:57 +03:00
//| Calendar Navigation |
2026-07-18 23:27:05 +03:00
//+==================================================================+
2026-07-20 07:45:57 +03:00
// datetime LastDayOfWeek(datetime) datetime FirstWeekdayOfMonth(datetime, MONDAY)
// datetime LastDayOfMonth(datetime) datetime LastWeekdayOfMonth(datetime, FRIDAY)
// datetime LastDayOfQuarter(datetime) datetime NthWeekdayOfYearMonth(2026, 11, Nth, FRIDAY)
// datetime LastDayOfYear(datetime)
2026-07-18 23:27:05 +03:00
2026-07-20 07:45:57 +03:00
// datetime NextDayOfWeek(datetime, MONDAY) datetime PreviousDayOfWeek(datetime, MONDAY)
// datetime NextSunday(datetime) datetime PreviousSunday(datetime)
// datetime NextMonday(datetime) datetime PreviousMonday(datetime)
// datetime NextTuesday(datetime) datetime PreviousTuesday(datetime)
// datetime NextWednesday(datetime) datetime PreviousWednesday(datetime)
// datetime NextThursday(datetime) datetime PreviousThursday(datetime)
// datetime NextFriday(datetime) datetime PreviousFriday(datetime)
// datetime NextSaturday(datetime) datetime PreviousSaturday(datetime)
2026-07-18 23:27:05 +03:00
//+==================================================================+
2026-07-20 07:45:57 +03:00
//| Rounding & Alignment |
2026-07-18 23:27:05 +03:00
//+==================================================================+
2026-07-20 07:45:57 +03:00
// datetime RoundToMinute(datetime) datetime CeilToMinute(datetime)
// datetime RoundToHour(datetime) datetime CeilToHour(datetime)
// datetime RoundToDay(datetime) datetime CeilToDay(datetime)
// datetime RoundToWeek(datetime) datetime CeilToWeek(datetime)
2026-07-18 23:27:05 +03:00
//+==================================================================+
2026-07-20 07:45:57 +03:00
//| Field Replacement |
2026-07-18 23:27:05 +03:00
//+==================================================================+
2026-07-20 07:45:57 +03:00
// datetime WithSecond(datetime, 30) datetime WithMonth(datetime, 12)
// datetime WithMinute(datetime, 45) datetime WithYear(datetime, 2030)
// datetime WithHour(datetime, 14) datetime WithTime(datetime, 14, 30, 0)
// datetime WithDay(datetime, 15) datetime WithDate(datetime, 2026, 7, 20)
// datetime WithDayOfWeek(datetime, FRIDAY)
2026-07-18 23:27:05 +03:00
//+==================================================================+
2026-07-20 07:45:57 +03:00
//| Arithmetic |
2026-07-18 23:27:05 +03:00
//+==================================================================+
2026-07-20 07:45:57 +03:00
// datetime AddSeconds(datetime, 30) datetime SubSeconds(datetime, 30)
// datetime AddMinutes(datetime, 15) datetime SubMinutes(datetime, 15)
// datetime AddHours(datetime, 8) datetime SubHours(datetime, 8)
// datetime AddDays(datetime, 5) datetime SubDays(datetime, 5)
// datetime AddBusinessDays(datetime, 5) datetime SubBusinessDays(datetime, 5)
// datetime AddWeeks(datetime, 2) datetime SubWeeks(datetime, 2)
// datetime AddMonths(datetime, 3) datetime SubMonths(datetime, 3)
// datetime AddQuarters(datetime, 2) datetime SubQuarters(datetime, 2)
// datetime AddYears(datetime, 10) datetime SubYears(datetime, 10)
2026-07-18 23:27:05 +03:00
2026-07-20 07:45:57 +03:00
// datetime AddPeriod(datetime, MqlDateTime period)
// datetime SubPeriod(datetime, MqlDateTime period)
2026-07-18 23:27:05 +03:00
//####################################################################
//# #
2026-07-20 07:45:57 +03:00
//# Differences & Duration #
2026-07-18 23:27:05 +03:00
//# #
//####################################################################
//+==================================================================+
2026-07-20 07:45:57 +03:00
//| Exact Time Durations |
2026-07-18 23:27:05 +03:00
//+==================================================================+
2026-07-20 07:45:57 +03:00
// DifferenceInSeconds(from, to) DifferenceInBusinessDays(from, to)
// DifferenceInMinutes(from, to) DifferenceInWeekendDays(from, to)
// DifferenceInHours(from, to)
// DifferenceInDays(from, to)
// DifferenceInWeeks(from, to)
// DifferenceInMonths(from, to)
// DifferenceInQuarters(from, to)
// DifferenceInYears(from, to)
2026-07-18 23:27:05 +03:00
//+==================================================================+
2026-07-20 07:45:57 +03:00
//| Calendar Differences |
2026-07-18 23:27:05 +03:00
//+==================================================================+
2026-07-20 07:45:57 +03:00
// DifferenceInCalendarDays(from, to) DifferenceInCalendarWeeks(from, to)
// DifferenceInCalendarMonths(from, to) DifferenceInCalendarQuarters(from, to)
// DifferenceInCalendarYears(from, to)
// CalendarDifference(from, to, MqlDateTime period)
// CalendarDifferenceToString(from, to)
2026-07-18 23:27:05 +03:00
//####################################################################
//# #
2026-07-20 07:45:57 +03:00
//# Validation & Comparison #
2026-07-18 23:27:05 +03:00
//# #
//####################################################################
//+==================================================================+
2026-07-20 07:45:57 +03:00
//| Day Checks |
2026-07-18 23:27:05 +03:00
//+==================================================================+
2026-07-20 07:45:57 +03:00
// IsWeekday(datetime) IsWeekend(datetime)
2026-07-18 23:27:05 +03:00
2026-07-20 07:45:57 +03:00
// IsSunday(datetime) IsThursday(datetime)
// IsMonday(datetime) IsFriday(datetime)
// IsTuesday(datetime) IsSaturday(datetime)
// IsWednesday(datetime)
2026-07-18 23:27:05 +03:00
2026-07-20 07:45:57 +03:00
// IsFirstDayOfMonth(datetime) IsToday(datetime)
// IsLastDayOfMonth(datetime) IsTomorrow(datetime)
// IsYesterday(datetime)
2026-07-18 23:27:05 +03:00
//+==================================================================+
2026-07-20 07:45:57 +03:00
//| Current Period |
2026-07-18 23:27:05 +03:00
//+==================================================================+
2026-07-20 07:45:57 +03:00
// IsCurrentMinute(datetime) IsCurrentMonth(datetime)
// IsCurrentHour(datetime) IsCurrentQuarter(datetime)
// IsCurrentWeek(datetime) IsCurrentYear(datetime)
2026-07-18 23:27:05 +03:00
//+==================================================================+
2026-07-20 07:45:57 +03:00
//| Equality |
2026-07-18 23:27:05 +03:00
//+==================================================================+
2026-07-20 07:45:57 +03:00
// IsSameMinute(a, b) IsSameMonth(a, b)
// IsSameHour(a, b) IsSameQuarter(a, b)
// IsSameDay(a, b) IsSameYear(a, b)
// IsSameWeek(a, b)
2026-07-18 23:27:05 +03:00
//+==================================================================+
2026-07-20 07:45:57 +03:00
//| Daily Trading Sessions |
2026-07-18 23:27:05 +03:00
//+==================================================================+
2026-07-20 07:45:57 +03:00
// IsInSession(datetime, IsInSession("08:00", "17:00")
// 8, 0, 17, 0)
2026-07-18 23:27:05 +03:00
2026-07-20 07:45:57 +03:00
// IsInSession(8, 0, 17, 0) bool SessionOverlap()
2026-07-18 23:27:05 +03:00
//####################################################################
//# #
2026-07-20 07:45:57 +03:00
//# Calendar Information #
2026-07-18 23:27:05 +03:00
//# #
//####################################################################
2026-07-20 07:45:57 +03:00
// DaysInMonth(2026, 7) WeeksInMonth(2026, 7)
// DaysInYear(2026) WeeksInYear(2026)
// IsLeapYear(2028)
//####################################################################
//# #
//# Formatting & Utilities #
//# #
//####################################################################
// DayName(ENUM_DAY_OF_WEEK)
// MonthName(7)
// SecondsToString(3661)
// t2s(datetime, TIME_DATE | TIME_MINUTES)
// TimeFormat(datetime, "YYYY.MM.DD hh:mm")
2026-07-18 23:27:05 +03:00
//+------------------------------------------------------------------+
//| Time unit conversion constants |
//+------------------------------------------------------------------+
# define MINSECS 60ULL
# define HOURSECS 3600ULL
# define DAYSECS 86400ULL
# define WEEKSECS 604800ULL
# define DAYS_PER_4_YEARS 1461U / / ( 4 * 365 ) + 1
# define DAYS_PER_400_YEARS 146097U / / DAYS_PER_4_YEARS * 100 - 3 non - leap century years .
# define DAYS_TO_1970 719162 / / Number of days from 1 / 1 / 0001 to 12 / 31 / 1969.
# define MARCH1_BASED_DOY 306 / / Number of days between March 1 and January 1.
2026-07-20 07:45:57 +03:00
// Offset used to align calendar week boundaries.
// 1970-01-01 (Unix epoch) was a Thursday.
# define WEEK_OFFSET \
( ( THURSDAY - ( int ) TIMEUTILS_FIRST_DAY_OF_WEEK ) * DAYSECS )
2026-07-18 23:27:05 +03:00
//####################################################################
//# #
//# Construction #
//# #
//####################################################################
//+==================================================================+
//| Create datetime From Components |
//+==================================================================+
//+------------------------------------------------------------------+
//| Create a datetime value from the specified date and time. |
//+------------------------------------------------------------------+
datetime DateFrom ( const int year , // Year
const int mon , // Month
const int day , // Day
const int hour = 0 , // Hour
const int min = 0 , // Minutes
const int sec = 0 ) // Seconds
{
MqlDateTime dt = { year , mon , day , hour , min , sec } ;
return StructToTimeFast ( dt ) ;
}
//+------------------------------------------------------------------+
//| Create a datetime from a formatted date/time string. |
//+------------------------------------------------------------------+
datetime DateFromString ( const string text )
{
return StringToTime ( text ) ;
}
//+------------------------------------------------------------------+
//| Faster alternative to MQL's StructToTime() function. |
//| Converts a structure variable MqlDateTime into a value of |
//| datetime type and returns the resulting value containing |
//| the number of seconds since 01.01.1970. |
//+------------------------------------------------------------------+
datetime StructToTimeFast ( const MqlDateTime & dt_struct )
{
const uint j = dt_struct . mon < 3 ;
const uint y = dt_struct . year - j ;
const uint m = j ? dt_struct . mon + 12 : dt_struct . mon ;
const uint f = ( 979 * m - 2918 ) / 32 ; // days before month
const uint n = dt_struct . day - 1 + f + 365 * y + ( y / 4 ) - ( y / 100 ) + ( y / 400 ) - DAYS_TO_1970 - MARCH1_BASED_DOY ;
return ( datetime ) ( ( n * DAYSECS ) + ( dt_struct . hour * HOURSECS ) + ( dt_struct . min * MINSECS ) + dt_struct . sec ) ;
}
//####################################################################
//# #
//# Calendar Components #
//# #
//####################################################################
//+==================================================================+
//| Break datetime To Components |
//+==================================================================+
//+------------------------------------------------------------------+
//| Faster alternative to MQL's TimeToStruct() function. |
//| Converts a value of datetime type (number of seconds |
//| since 01.01.1970) into a structure variable MqlDateTime. |
//| https://github.com/cassioneri/eaf/blob/main/algorithms/neri_schneider.hpp
//+------------------------------------------------------------------+
bool TimeToStructFast ( const datetime time , MqlDateTime & dt_struct )
{
uint n = ( uint ) ( time / DAYSECS ) ; // Unix day
uint N = n + 12699422 ; // Computational calendar day
uint a = 4 * N + 3 ; // N_1
uint c = a / DAYS_PER_400_YEARS ; // century
uint e = a % DAYS_PER_400_YEARS / 4 ; // [0, 36524] - dayOfCentury
uint b = 4 * e + 3 ; // N_2
uint z = b / DAYS_PER_4_YEARS ; // [0, 99] - yearOfCentury
uint h = b % DAYS_PER_4_YEARS / 4 ; // [0, 365] - Days since 1 March
uint d = 2141 * h + 197913 ; // N_3
uint M = d / 65536 ; // [3, 14] - Month
uint D = d % 65536 / 2141U ; // [0, 30] - Day
uint Y = 100 * c + z ; // Year
uint J = h > = MARCH1_BASED_DOY ; // JanFeb
uint l = z ? ( z % 4 = = 0 ) : ( c % 4 = = 0 ) ; // isLeap
uint seconds = ( uint ) ( time - n * DAYSECS ) ;
uint minutes = seconds / 60 ;
uint hours = minutes / 60 ;
dt_struct . year = ( int ) ( Y - 32800 + J ) ;
dt_struct . mon = ( int ) ( J ? M - 12 : M ) ;
dt_struct . day = ( int ) ( D + 1 ) ;
dt_struct . hour = ( int ) ( hours ) ;
dt_struct . min = ( int ) ( minutes - ( hours * 60 ) ) ;
dt_struct . sec = ( int ) ( seconds - ( minutes * 60 ) ) ;
dt_struct . day_of_week = ( int ) ( ( n + 4 ) % 7U ) ;
dt_struct . day_of_year = ( int ) ( h + ( J ? - MARCH1_BASED_DOY : 59 + l ) ) ;
return ( true ) ;
}
//+==================================================================+
//| Extract Components of datetime: Sunday, yyyy.mm.dd hh:mm:ss |
//| Get() Units |
//+==================================================================+
int Second ( void ) { return Second ( TimeTradeServer ( ) ) ; } // gets current second (0..59)
int Minute ( void ) { return Minute ( TimeTradeServer ( ) ) ; } // gets current minute (0..59)
int Hour ( void ) { return Hour ( TimeTradeServer ( ) ) ; } // gets current hour (0..23)
int Day ( void ) { return Day ( TimeTradeServer ( ) ) ; } // gets day of current month (1..31)
int Month ( void ) { return Month ( TimeTradeServer ( ) ) ; } // gets current month (1..12)
int Year ( void ) { return Year ( TimeTradeServer ( ) ) ; } // gets current year (1970..3000)
int DayOfWeek ( void ) { return DayOfWeek ( TimeTradeServer ( ) ) ; } // gets day of current week (0..6)
int DayOfYear ( void ) { return DayOfYear ( TimeTradeServer ( ) ) ; } // gets day of current year (0..365)
//+------------------------------------------------------------------+
//| Return seconds of minute as integer (0..59) |
//+------------------------------------------------------------------+
int Second ( const datetime t )
{
return ( int ) ( t % MINSECS ) ;
}
//+------------------------------------------------------------------+
//| Return minutes of hour as integer (0..59) |
//+------------------------------------------------------------------+
int Minute ( const datetime t )
{
return ( int ) ( ( t / MINSECS ) % MINSECS ) ;
}
//+------------------------------------------------------------------+
//| Return hour of day as integer (0..23) |
//+------------------------------------------------------------------+
int Hour ( const datetime t )
{
return ( int ) ( ( t / HOURSECS ) % 24U ) ;
}
//+------------------------------------------------------------------+
//| Return day of month as integer (1..31) |
//+------------------------------------------------------------------+
int Day ( const datetime t )
{
// MqlDateTime dt;
// TimeToStructFast(t, dt);
// return(dt.day);
uint dayOfCentury = ( ( ( ( uint ) ( t / DAYSECS ) + DAYS_TO_1970 + MARCH1_BASED_DOY ) < < 2 ) | 3U ) % DAYS_PER_400_YEARS ;
uint daySinceMarch1 = ( dayOfCentury | 3U ) % DAYS_PER_4_YEARS / 4 ;
uint monthDayPacked = daySinceMarch1 * 2141 + 197913 ;
return ( int ) ( ( monthDayPacked & 0xFFFF ) / 2141 ) + 1 ;
}
//+------------------------------------------------------------------+
//| Return the month number as integer (1..12) |
//+------------------------------------------------------------------+
int Month ( const datetime t )
{
// MqlDateTime dt;
// TimeToStructFast(t, dt);
// return(dt.mon);
uint dayOfCentury = ( ( ( ( uint ) ( t / DAYSECS ) + DAYS_TO_1970 + MARCH1_BASED_DOY ) < < 2 ) | 3U ) % DAYS_PER_400_YEARS ;
uint daySinceMarch1 = ( dayOfCentury | 3U ) % DAYS_PER_4_YEARS / 4 ;
uint monthDayPacked = daySinceMarch1 * 2141 + 197913 ;
return ( int ) ( monthDayPacked > > 16 ) - ( daySinceMarch1 > = MARCH1_BASED_DOY ? 12 : 0 ) ;
}
//+------------------------------------------------------------------+
//| Return the year as integer (1970..3000) |
//+------------------------------------------------------------------+
int Year ( const datetime t )
{
// MqlDateTime dt;
// TimeToStructFast(t, dt);
// return(dt.year);
uint days = ( ( ( ( uint ) ( t / DAYSECS ) + DAYS_TO_1970 ) < < 2 ) | 3U ) ;
uint century = days / DAYS_PER_400_YEARS ;
uint year = ( ( days % DAYS_PER_400_YEARS ) | 3U ) / DAYS_PER_4_YEARS ;
return ( int ) ( 100 * century + year ) + 1 ;
}
//+------------------------------------------------------------------+
//| Return the date part for the given date. |
//+------------------------------------------------------------------+
datetime DateOnly ( const datetime t )
{
return StartOfDay ( t ) ;
}
//+------------------------------------------------------------------+
//| Return the time part for the given date. |
//+------------------------------------------------------------------+
datetime TimeOnly ( const datetime t )
{
return ( datetime ) SecsElapsedOfDay ( t ) ;
}
//+==================================================================+
//| Day() Numbering |
//+==================================================================+
//+------------------------------------------------------------------+
//| Day of the week as integer (0 = Sunday to 6 = Saturday) |
//+------------------------------------------------------------------+
int DayOfWeek ( const datetime t )
{
return ( int ) ( ( t / DAYSECS + THURSDAY ) % 7U ) ; // 1 Jan 1970 is Thursday
}
//+------------------------------------------------------------------+
2026-07-20 07:45:57 +03:00
//| Returns the zero-based day of the year as integer (0...365) |
2026-07-18 23:27:05 +03:00
//+------------------------------------------------------------------+
int DayOfYear ( const datetime t )
{
return ( int ) ( ( ( ( ( ( ( uint ) ( t / DAYSECS ) + DAYS_TO_1970 ) < < 2 ) | 3U ) % DAYS_PER_400_YEARS ) | 3U ) % DAYS_PER_4_YEARS ) > > 2 ;
}
//+==================================================================+
2026-07-20 07:45:57 +03:00
//| Quarter of Year |
2026-07-18 23:27:05 +03:00
//+==================================================================+
//+------------------------------------------------------------------+
2026-07-20 07:45:57 +03:00
//| Return the year quarter number (1..4). |
2026-07-18 23:27:05 +03:00
//+------------------------------------------------------------------+
2026-07-20 07:45:57 +03:00
int Quarter ( const datetime t )
2026-07-18 23:27:05 +03:00
{
2026-07-20 07:45:57 +03:00
return ( ( Month ( t ) - 1 ) / 3 ) + 1 ;
2026-07-18 23:27:05 +03:00
}
//+==================================================================+
//| Epoch-Based Indices |
//+==================================================================+
//+------------------------------------------------------------------+
//| Returns the zero-based minute index since 1970-01-01 00:00. |
//+------------------------------------------------------------------+
int MinuteIndex ( const datetime t )
{
return ( int ) ( t / MINSECS ) ;
}
//+------------------------------------------------------------------+
//| Returns the zero-based hour index since 1970-01-01 00:00. |
//+------------------------------------------------------------------+
int HourIndex ( const datetime t )
{
return ( int ) ( t / HOURSECS ) ;
}
//+------------------------------------------------------------------+
//| Returns the zero-based day index since 1970-01-01. |
//| Useful for indicators to determine the first bar of the new day: |
//| bool NewDay = DayIndex(time[i]) != DayIndex(time[i-1]); |
//+------------------------------------------------------------------+
int DayIndex ( const datetime t )
{
return ( int ) ( t / DAYSECS ) ;
}
//+------------------------------------------------------------------+
2026-07-20 07:45:57 +03:00
//| Returns the zero-based calendar week index since the week |
//| containing 1970-01-01. |
//| The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
2026-07-18 23:27:05 +03:00
//+------------------------------------------------------------------+
int WeekIndex ( const datetime t )
{
2026-07-20 07:45:57 +03:00
return ( int ) ( ( t + WEEK_OFFSET ) / WEEKSECS ) ;
2026-07-18 23:27:05 +03:00
}
//+------------------------------------------------------------------+
//| Returns the zero-based calendar month index since 1970-01. |
//+------------------------------------------------------------------+
int MonthIndex ( const datetime t )
{
return ( Year ( t ) - 1970 ) * 12 + Month ( t ) - 1 ;
}
//+------------------------------------------------------------------+
//| Returns the zero-based calendar quarter index since 1970 Q1. |
//+------------------------------------------------------------------+
int QuarterIndex ( const datetime t )
{
return ( Year ( t ) - 1970 ) * 4 + Quarter ( t ) - 1 ;
}
//+------------------------------------------------------------------+
//| Returns the zero-based calendar year index since 1970. |
//+------------------------------------------------------------------+
int YearIndex ( const datetime t )
{
return Year ( t ) - 1970 ;
}
//+==================================================================+
//| HourOf() Units |
//+==================================================================+
//+------------------------------------------------------------------+
//| Hours elapsed from the start of week for the given date. |
2026-07-20 07:45:57 +03:00
//| The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
2026-07-18 23:27:05 +03:00
//+------------------------------------------------------------------+
int HourOfWeek ( const datetime t )
{
return ( int ) ( SecsElapsedOfWeek ( t ) / HOURSECS ) ;
}
//+------------------------------------------------------------------+
//| Hours elapsed from the start of month for the given date. |
//+------------------------------------------------------------------+
int HourOfMonth ( const datetime t )
{
return ( int ) ( SecsElapsedOfMonth ( t ) / HOURSECS ) ;
}
//+------------------------------------------------------------------+
//| Hours elapsed from the start of quarter for the given date. |
//+------------------------------------------------------------------+
int HourOfQuarter ( const datetime t )
{
return ( int ) ( SecsElapsedOfQuarter ( t ) / HOURSECS ) ;
}
//+------------------------------------------------------------------+
//| Hours elapsed from the start of year for the given date. |
//+------------------------------------------------------------------+
int HourOfYear ( const datetime t )
{
return ( int ) ( SecsElapsedOfYear ( t ) / HOURSECS ) ;
}
//+==================================================================+
//| MinuteOf() Units |
//+==================================================================+
//+------------------------------------------------------------------+
//| Minutes elapsed from the start of day for the given date. |
//+------------------------------------------------------------------+
int MinuteOfDay ( const datetime t )
{
return ( int ) ( SecsElapsedOfDay ( t ) / MINSECS ) ;
}
//+------------------------------------------------------------------+
//| Minutes elapsed from the start of week for the given date. |
2026-07-20 07:45:57 +03:00
//| The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
2026-07-18 23:27:05 +03:00
//+------------------------------------------------------------------+
int MinuteOfWeek ( const datetime t )
{
return ( int ) ( SecsElapsedOfWeek ( t ) / MINSECS ) ;
}
//+------------------------------------------------------------------+
//| Minutes elapsed from the start of month for the given date. |
//+------------------------------------------------------------------+
int MinuteOfMonth ( const datetime t )
{
return ( int ) ( SecsElapsedOfMonth ( t ) / MINSECS ) ;
}
//+------------------------------------------------------------------+
//| Minutes elapsed from the start of quarter for the given date. |
//+------------------------------------------------------------------+
int MinuteOfQuarter ( const datetime t )
{
return ( int ) ( SecsElapsedOfQuarter ( t ) / MINSECS ) ;
}
//+------------------------------------------------------------------+
//| Minutes elapsed from the start of year for the given date. |
//+------------------------------------------------------------------+
int MinuteOfYear ( const datetime t )
{
return ( int ) ( SecsElapsedOfYear ( t ) / MINSECS ) ;
}
//+==================================================================+
//| SecsElapsedOf() Units |
//+==================================================================+
//+------------------------------------------------------------------+
//| Seconds elapsed from the start of minute for the given date. |
//+------------------------------------------------------------------+
int SecsElapsedOfMinute ( const datetime t )
{
return ( int ) ( t % MINSECS ) ;
}
//+------------------------------------------------------------------+
//| Seconds elapsed from the start of hour for the given date. |
//+------------------------------------------------------------------+
int SecsElapsedOfHour ( const datetime t )
{
return ( int ) ( t % HOURSECS ) ;
}
//+------------------------------------------------------------------+
//| Seconds elapsed from the start of day for the given date. |
//+------------------------------------------------------------------+
int SecsElapsedOfDay ( const datetime t )
{
return ( int ) ( t % DAYSECS ) ;
}
//+------------------------------------------------------------------+
//| Seconds elapsed from the start of day for the given date. |
//+------------------------------------------------------------------+
int SecondsSinceMidnight ( const datetime t )
{
return ( int ) ( t % DAYSECS ) ;
}
//+------------------------------------------------------------------+
//| Seconds elapsed from the start of week for the given date. |
2026-07-20 07:45:57 +03:00
//| The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
2026-07-18 23:27:05 +03:00
//+------------------------------------------------------------------+
int SecsElapsedOfWeek ( const datetime t )
{
2026-07-20 07:45:57 +03:00
return ( int ) ( ( t + WEEK_OFFSET ) % WEEKSECS ) ;
2026-07-18 23:27:05 +03:00
}
//+------------------------------------------------------------------+
//| Seconds elapsed from the start of month for the given date. |
//+------------------------------------------------------------------+
int SecsElapsedOfMonth ( const datetime t )
{
return ( int ) ( t - StartOfMonth ( t ) ) ;
}
//+------------------------------------------------------------------+
//| Seconds elapsed from the start of quarter for the given date. |
//+------------------------------------------------------------------+
int SecsElapsedOfQuarter ( const datetime t )
{
return ( int ) ( t - StartOfQuarter ( t ) ) ;
}
//+------------------------------------------------------------------+
//| Seconds elapsed from the start of year for the given date. |
//+------------------------------------------------------------------+
int SecsElapsedOfYear ( const datetime t )
{
return ( int ) ( t - StartOfYear ( t ) ) ;
}
//+------------------------------------------------------------------+
//| Seconds elapsed since 1 Jan 1970 (Unix epoch) for the given date.|
//+------------------------------------------------------------------+
long SecsElapsedOfEpoch ( const datetime t )
{
return ( long ) ( t ) ;
}
//####################################################################
//# #
//# Adjusters / Navigation #
//# #
//####################################################################
//+==================================================================+
//| StartOf() / FloorTo() Units |
//+==================================================================+
//+------------------------------------------------------------------+
//| Return the start of a minute for the given date. |
//+------------------------------------------------------------------+
datetime StartOfMinute ( const datetime t )
{
return t - ( t % MINSECS ) ;
}
//+------------------------------------------------------------------+
//| Return the start of an hour for the given date. |
//+------------------------------------------------------------------+
datetime StartOfHour ( const datetime t )
{
return t - ( t % HOURSECS ) ;
}
//+------------------------------------------------------------------+
//| Return the start of a day for the given date. |
//+------------------------------------------------------------------+
datetime StartOfDay ( const datetime t )
{
return t - ( t % DAYSECS ) ;
}
//+------------------------------------------------------------------+
2026-07-20 07:45:57 +03:00
//| Returns the start of the calendar week containing the given |
//| date/time. The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
2026-07-18 23:27:05 +03:00
//+------------------------------------------------------------------+
datetime StartOfWeek ( const datetime t )
{
2026-07-20 07:45:57 +03:00
return t - ( ( t + WEEK_OFFSET ) % WEEKSECS ) ;
2026-07-18 23:27:05 +03:00
}
//+------------------------------------------------------------------+
//| Return the first day of a month for the given date. |
//+------------------------------------------------------------------+
datetime StartOfMonth ( const datetime t )
{
const int y = Year ( t ) ;
const int m = Month ( t ) ;
return DateFrom ( y , m , 1 ) ;
}
//+------------------------------------------------------------------+
//| Return the first day of a year quarter for the given date. |
//+------------------------------------------------------------------+
datetime StartOfQuarter ( const datetime t )
{
const int y = Year ( t ) ;
const int m = Month ( t ) ;
const int qMonth = ( ( m - 1 ) / 3 ) * 3 + 1 ;
return DateFrom ( y , qMonth , 1 ) ;
}
//+------------------------------------------------------------------+
//| Return the first day of a year for the given date. |
//+------------------------------------------------------------------+
datetime StartOfYear ( const datetime t )
{
const int y = Year ( t ) ;
return DateFrom ( y , 1 , 1 ) ;
}
//+------------------------------------------------------------------+
//| Return the start second of today on the trade server. |
//+------------------------------------------------------------------+
datetime StartOfToday ( void )
{
return StartOfDay ( TimeTradeServer ( ) ) ;
}
//+------------------------------------------------------------------+
//| Return the start second of tomorrow on the trade server. |
//+------------------------------------------------------------------+
datetime StartOfTomorrow ( void )
{
return AddDays ( StartOfDay ( TimeTradeServer ( ) ) , 1 ) ;
}
//+------------------------------------------------------------------+
//| Return the start second of yesterday on the trade server. |
//+------------------------------------------------------------------+
datetime StartOfYesterday ( void )
{
return SubDays ( StartOfDay ( TimeTradeServer ( ) ) , 1 ) ;
}
//+==================================================================+
//| EndOf() Units |
//+==================================================================+
//+------------------------------------------------------------------+
//| Return the last second of a minute for the given date. |
//+------------------------------------------------------------------+
datetime EndOfMinute ( const datetime t )
{
return StartOfMinute ( t ) + ( MINSECS - 1 ) ;
}
//+------------------------------------------------------------------+
//| Return the last second of an hour for the given date. |
//+------------------------------------------------------------------+
datetime EndOfHour ( const datetime t )
{
return StartOfHour ( t ) + ( HOURSECS - 1 ) ;
}
//+------------------------------------------------------------------+
//| Return the last second of a day for the given date. |
//+------------------------------------------------------------------+
datetime EndOfDay ( const datetime t )
{
return StartOfDay ( t ) + ( DAYSECS - 1 ) ;
}
//+------------------------------------------------------------------+
//| Return the last second of a week for the given date. |
2026-07-20 07:45:57 +03:00
//| The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
2026-07-18 23:27:05 +03:00
//+------------------------------------------------------------------+
datetime EndOfWeek ( const datetime t )
{
return StartOfWeek ( t ) + ( WEEKSECS - 1 ) ;
}
//+------------------------------------------------------------------+
//| Return the last second of a month for the given date. |
//+------------------------------------------------------------------+
datetime EndOfMonth ( const datetime t )
{
// MqlDateTime dt;
// TimeToStructFast(t, dt);
// dt.day = DaysInMonth(dt.year, dt.mon);
// dt.hour = 23;
// dt.min = 59;
// dt.sec = 59;
// return(StructToTimeFast(dt));
int y = Year ( t ) ;
int m = Month ( t ) ;
m = ( m % 12 ) + 1 ;
y + = ( m = = 1 ) ;
return DateFrom ( y , m , 1 ) - 1 ;
}
//+------------------------------------------------------------------+
//| Return the last second of a year quarter for the given date. |
//+------------------------------------------------------------------+
datetime EndOfQuarter ( const datetime t )
{
return EndOfMonth ( AddMonths ( StartOfQuarter ( t ) , 2 ) ) ;
}
//+------------------------------------------------------------------+
//| Return the last second of a year for the given date. |
//+------------------------------------------------------------------+
datetime EndOfYear ( const datetime t )
{
const int y = Year ( t ) ;
return DateFrom ( ( y + 1 ) , 1 , 1 ) - 1 ;
}
//+------------------------------------------------------------------+
//| Return the last second of today on the trade server. |
//+------------------------------------------------------------------+
datetime EndOfToday ( void )
{
return EndOfDay ( TimeTradeServer ( ) ) ;
}
//+------------------------------------------------------------------+
//| Return the last second of tomorrow on the trade server. |
//+------------------------------------------------------------------+
datetime EndOfTomorrow ( void )
{
return AddDays ( EndOfDay ( TimeTradeServer ( ) ) , 1 ) ;
}
//+------------------------------------------------------------------+
//| Return the last second of yesterday on the trade server. |
//+------------------------------------------------------------------+
datetime EndOfYesterday ( void )
{
return SubDays ( EndOfDay ( TimeTradeServer ( ) ) , 1 ) ;
}
//+==================================================================+
//| LastDayOf() Units |
//+==================================================================+
//+------------------------------------------------------------------+
2026-07-20 07:45:57 +03:00
//| Return the last day of a week for the given date. |
//| The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
2026-07-18 23:27:05 +03:00
//+------------------------------------------------------------------+
datetime LastDayOfWeek ( const datetime t )
{
return EndOfWeek ( t ) - ( DAYSECS - 1 ) ;
}
//+------------------------------------------------------------------+
//| Return the last day of a month for the given date. |
//+------------------------------------------------------------------+
datetime LastDayOfMonth ( const datetime t )
{
return EndOfMonth ( t ) - ( DAYSECS - 1 ) ;
}
//+------------------------------------------------------------------+
//| Return the last day of a year quarter for the given date. |
//+------------------------------------------------------------------+
datetime LastDayOfQuarter ( const datetime t )
{
return EndOfQuarter ( t ) - ( DAYSECS - 1 ) ;
}
//+------------------------------------------------------------------+
//| Return the last day of a year for the given date. |
//+------------------------------------------------------------------+
datetime LastDayOfYear ( const datetime t )
{
return EndOfYear ( t ) - ( DAYSECS - 1 ) ;
}
//+==================================================================+
//| RoundTo() / Nearest() Units |
//+==================================================================+
//+------------------------------------------------------------------+
//| Rounds halfway the given date to the nearest minute. |
//+------------------------------------------------------------------+
datetime RoundToMinute ( const datetime t )
{
return StartOfMinute ( t + MINSECS / 2 ) ;
}
//+------------------------------------------------------------------+
//| Rounds halfway the given date to the nearest hour. |
//+------------------------------------------------------------------+
datetime RoundToHour ( const datetime t )
{
return StartOfHour ( t + HOURSECS / 2 ) ;
}
//+------------------------------------------------------------------+
//| Rounds halfway the given date to the nearest day. |
//+------------------------------------------------------------------+
datetime RoundToDay ( const datetime t )
{
return StartOfDay ( t + DAYSECS / 2 ) ;
}
//+------------------------------------------------------------------+
//| Rounds halfway the given date to the nearest week. |
2026-07-20 07:45:57 +03:00
//| The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
2026-07-18 23:27:05 +03:00
//+------------------------------------------------------------------+
datetime RoundToWeek ( const datetime t )
{
return StartOfWeek ( t + WEEKSECS / 2 ) ;
}
//+==================================================================+
//| CeilTo() / Next() Units |
//+==================================================================+
//+------------------------------------------------------------------+
//| Rounds up the given date to the next minute. |
//+------------------------------------------------------------------+
datetime CeilToMinute ( const datetime t )
{
return StartOfMinute ( t + MINSECS - 1 ) ;
}
//+------------------------------------------------------------------+
//| Rounds up the given date to the next hour. |
//+------------------------------------------------------------------+
datetime CeilToHour ( const datetime t )
{
return StartOfHour ( t + HOURSECS - 1 ) ;
}
//+------------------------------------------------------------------+
//| Rounds up the given date to the next day. |
//+------------------------------------------------------------------+
datetime CeilToDay ( const datetime t )
{
return StartOfDay ( t + DAYSECS - 1 ) ;
}
//+------------------------------------------------------------------+
//| Rounds up the given date to the next week. |
2026-07-20 07:45:57 +03:00
//| The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
2026-07-18 23:27:05 +03:00
//+------------------------------------------------------------------+
datetime CeilToWeek ( const datetime t )
{
return StartOfWeek ( t + WEEKSECS - 1 ) ;
}
//+==================================================================+
//| Next() Weekday |
//+==================================================================+
//+------------------------------------------------------------------+
//| Return the next occurrence of a weekday after the given date. |
//+------------------------------------------------------------------+
2026-07-20 07:45:57 +03:00
datetime NextDayOfWeek ( const datetime t ,
const ENUM_DAY_OF_WEEK weekday = SUNDAY )
2026-07-18 23:27:05 +03:00
{
int delta = weekday - DayOfWeek ( t ) ;
if ( delta < = 0 )
delta + = 7 ;
return AddDays ( StartOfDay ( t ) , delta ) ;
}
//+------------------------------------------------------------------+
//| When is the next Sunday? |
//+------------------------------------------------------------------+
datetime NextSunday ( const datetime t )
{
return NextDayOfWeek ( t , SUNDAY ) ;
}
//+------------------------------------------------------------------+
//| When is the next Monday? |
//+------------------------------------------------------------------+
datetime NextMonday ( const datetime t )
{
return NextDayOfWeek ( t , MONDAY ) ;
}
//+------------------------------------------------------------------+
//| When is the next Tuesday? |
//+------------------------------------------------------------------+
datetime NextTuesday ( const datetime t )
{
return NextDayOfWeek ( t , TUESDAY ) ;
}
//+------------------------------------------------------------------+
//| When is the next Wednesday? |
//+------------------------------------------------------------------+
datetime NextWednesday ( const datetime t )
{
return NextDayOfWeek ( t , WEDNESDAY ) ;
}
//+------------------------------------------------------------------+
//| When is the next Thursday? |
//+------------------------------------------------------------------+
datetime NextThursday ( const datetime t )
{
return NextDayOfWeek ( t , THURSDAY ) ;
}
//+------------------------------------------------------------------+
//| When is the next Friday? |
//+------------------------------------------------------------------+
datetime NextFriday ( const datetime t )
{
return NextDayOfWeek ( t , FRIDAY ) ;
}
//+------------------------------------------------------------------+
//| When is the next Saturday? |
//+------------------------------------------------------------------+
datetime NextSaturday ( const datetime t )
{
return NextDayOfWeek ( t , SATURDAY ) ;
}
//+==================================================================+
//| Previous() Weekday |
//+==================================================================+
//+------------------------------------------------------------------+
//| Return the previous occurrence of a weekday before the given date. |
//+------------------------------------------------------------------+
2026-07-20 07:45:57 +03:00
datetime PreviousDayOfWeek ( const datetime t ,
const ENUM_DAY_OF_WEEK weekday = SUNDAY )
2026-07-18 23:27:05 +03:00
{
int delta = DayOfWeek ( t ) - weekday ;
if ( delta < = 0 )
delta + = 7 ;
return SubDays ( StartOfDay ( t ) , delta ) ;
}
//+------------------------------------------------------------------+
//| When is the previous Sunday? |
//+------------------------------------------------------------------+
datetime PreviousSunday ( const datetime t )
{
return PreviousDayOfWeek ( t , SUNDAY ) ;
}
//+------------------------------------------------------------------+
//| When is the previous Monday? |
//+------------------------------------------------------------------+
datetime PreviousMonday ( const datetime t )
{
return PreviousDayOfWeek ( t , MONDAY ) ;
}
//+------------------------------------------------------------------+
//| When is the previous Tuesday? |
//+------------------------------------------------------------------+
datetime PreviousTuesday ( const datetime t )
{
return PreviousDayOfWeek ( t , TUESDAY ) ;
}
//+------------------------------------------------------------------+
//| When is the previous Wednesday? |
//+------------------------------------------------------------------+
datetime PreviousWednesday ( const datetime t )
{
return PreviousDayOfWeek ( t , WEDNESDAY ) ;
}
//+------------------------------------------------------------------+
//| When is the previous Thursday? |
//+------------------------------------------------------------------+
datetime PreviousThursday ( const datetime t )
{
return PreviousDayOfWeek ( t , THURSDAY ) ;
}
//+------------------------------------------------------------------+
//| When is the previous Friday? |
//+------------------------------------------------------------------+
datetime PreviousFriday ( const datetime t )
{
return PreviousDayOfWeek ( t , FRIDAY ) ;
}
//+------------------------------------------------------------------+
//| When is the previous Saturday? |
//+------------------------------------------------------------------+
datetime PreviousSaturday ( const datetime t )
{
return PreviousDayOfWeek ( t , SATURDAY ) ;
}
//+==================================================================+
//| Nth() Weekday |
//+==================================================================+
//+------------------------------------------------------------------+
//| Return the Nth weekday of the given year and month. |
//| |
//| Nth > 0 : 1 = first, 2 = second, ... |
//| Nth < 0 : -1 = last, -2 = second last, ... |
//| Returns 0 if the requested occurrence does not exist. |
//+------------------------------------------------------------------+
datetime NthWeekdayOfYearMonth ( const int year ,
const int month ,
const int Nth ,
const ENUM_DAY_OF_WEEK weekday = SUNDAY )
{
if ( Nth = = 0 | | month < 1 | | month > 12 )
return 0 ;
const datetime first = DateFrom ( year , month , 1 ) ;
const datetime last = DateFrom ( year , month , DaysInMonth ( year , month ) ) ;
int jumpdays = ( MathAbs ( Nth ) - 1 ) * 7 ;
if ( Nth > 0 )
{
// Count from the beginning of the month.
jumpdays + = ( 7 + weekday - DayOfWeek ( first ) ) % 7 ;
datetime result = AddDays ( first , jumpdays ) ;
return ( result < = last ) ? result : 0 ;
}
else
{
// Count from the end of the month.
jumpdays + = ( 7 - weekday + DayOfWeek ( last ) ) % 7 ;
datetime result = SubDays ( last , jumpdays ) ;
return ( result > = first ) ? result : 0 ;
}
}
//+------------------------------------------------------------------+
//| Return the first weekday of the month. |
//+------------------------------------------------------------------+
2026-07-20 07:45:57 +03:00
datetime FirstWeekdayOfMonth ( const datetime t ,
const ENUM_DAY_OF_WEEK weekday = SUNDAY )
2026-07-18 23:27:05 +03:00
{
return NthWeekdayOfYearMonth ( Year ( t ) , Month ( t ) , 1 , weekday ) ;
}
//+------------------------------------------------------------------+
//| Return the last weekday of the month. |
//+------------------------------------------------------------------+
2026-07-20 07:45:57 +03:00
datetime LastWeekdayOfMonth ( const datetime t ,
const ENUM_DAY_OF_WEEK weekday = SUNDAY )
2026-07-18 23:27:05 +03:00
{
return NthWeekdayOfYearMonth ( Year ( t ) , Month ( t ) , -1 , weekday ) ;
}
//+==================================================================+
//| WithXxx() / Replace() Units |
//+==================================================================+
//+------------------------------------------------------------------+
//| Returns a copy of the given datetime with the second updated. |
//+------------------------------------------------------------------+
datetime WithSecond ( const datetime t , const int second )
{
if ( second < 0 | | second > 59 )
return -1 ;
return AddSeconds ( t , second - Second ( t ) ) ;
}
//+------------------------------------------------------------------+
//| Returns a copy of the given datetime with the minute updated. |
//+------------------------------------------------------------------+
datetime WithMinute ( const datetime t , const int minute )
{
if ( minute < 0 | | minute > 59 )
return -1 ;
return AddMinutes ( t , minute - Minute ( t ) ) ;
}
//+------------------------------------------------------------------+
//| Returns a copy of the given datetime with the hour updated. |
//+------------------------------------------------------------------+
datetime WithHour ( const datetime t , const int hour )
{
if ( hour < 0 | | hour > 23 )
return -1 ;
return AddHours ( t , hour - Hour ( t ) ) ;
}
//+------------------------------------------------------------------+
//| Returns a copy of the given datetime with the day of month updated.|
//+------------------------------------------------------------------+
datetime WithDay ( const datetime t , const int day )
{
if ( day < 1 | | day > DaysInMonth ( Year ( t ) , Month ( t ) ) )
return -1 ;
return AddDays ( t , day - Day ( t ) ) ;
}
//+------------------------------------------------------------------+
//| Returns a copy of the given datetime with the month updated. |
//+------------------------------------------------------------------+
datetime WithMonth ( const datetime t , const int month )
{
if ( month < 1 | | month > 12 )
return -1 ;
return AddMonths ( t , month - Month ( t ) ) ;
}
//+------------------------------------------------------------------+
//| Returns a copy of the given datetime with the year updated. |
//+------------------------------------------------------------------+
datetime WithYear ( const datetime t , const int year )
{
if ( year < 1970 | | year > 3000 )
return -1 ;
return AddYears ( t , year - Year ( t ) ) ;
}
//+------------------------------------------------------------------+
//| Returns a copy of the given datetime adjusted to the specified |
//| weekday within the current week, preserving the time of day. |
2026-07-20 07:45:57 +03:00
//| The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
2026-07-18 23:27:05 +03:00
//+------------------------------------------------------------------+
2026-07-20 07:45:57 +03:00
datetime WithDayOfWeek ( const datetime t ,
const ENUM_DAY_OF_WEEK weekday )
2026-07-18 23:27:05 +03:00
{
2026-07-20 07:45:57 +03:00
const int first = ( int ) TIMEUTILS_FIRST_DAY_OF_WEEK ;
const int current = DayOfWeek ( t ) ;
int delta = ( int ) weekday - current ;
2026-07-18 23:27:05 +03:00
2026-07-20 07:45:57 +03:00
if ( ( int ) weekday < first )
delta + = 7 ;
2026-07-18 23:27:05 +03:00
2026-07-20 07:45:57 +03:00
if ( current < first )
delta - = 7 ;
2026-07-18 23:27:05 +03:00
2026-07-20 07:45:57 +03:00
return AddDays ( t , delta ) ;
2026-07-18 23:27:05 +03:00
}
//+------------------------------------------------------------------+
//| Returns a copy of the given datetime with the specified time, |
//| preserving the date (i.e., replace time). |
//+------------------------------------------------------------------+
datetime WithTime ( const datetime t ,
const int hour ,
const int minute ,
const int second )
{
if ( hour < 0 | | hour > 23 | |
minute < 0 | | minute > 59 | |
second < 0 | | second > 59 )
return -1 ;
datetime res = t ;
res = WithHour ( res , hour ) ;
res = WithMinute ( res , minute ) ;
return WithSecond ( res , second ) ;
}
//+------------------------------------------------------------------+
//| Returns a copy of the given datetime with the specified date, |
//| preserving the time of day (i.e., replace date). |
//+------------------------------------------------------------------+
datetime WithDate ( const datetime t ,
const int year ,
const int month ,
const int day )
{
MqlDateTime dt ;
TimeToStructFast ( t , dt ) ;
if ( year < 1970 | | year > 3000 | |
month < 1 | | month > 12 | |
day < 1 | | day > DaysInMonth ( year , month ) )
return -1 ;
dt . year = year ;
dt . mon = month ;
dt . day = day ;
return StructToTimeFast ( dt ) ;
}
//####################################################################
//# #
//# Addition and Subtraction #
//# #
//####################################################################
//+==================================================================+
//| Add() Units |
//+==================================================================+
//+------------------------------------------------------------------+
//| Add the specified number of seconds to the given date. |
//+------------------------------------------------------------------+
datetime AddSeconds ( const datetime t , const int amount )
{
return t + amount ;
}
//+------------------------------------------------------------------+
//| Add the specified number of minutes to the given date. |
//+------------------------------------------------------------------+
datetime AddMinutes ( const datetime t , const int amount )
{
return t + ( ( datetime ) amount * MINSECS ) ;
}
//+------------------------------------------------------------------+
//| Add the specified number of hours to the given date. |
//+------------------------------------------------------------------+
datetime AddHours ( const datetime t , const int amount )
{
return t + ( ( datetime ) amount * HOURSECS ) ;
}
//+------------------------------------------------------------------+
//| Add the specified number of days to the given date. |
//+------------------------------------------------------------------+
datetime AddDays ( const datetime t , const int amount )
{
return t + ( ( datetime ) amount * DAYSECS ) ;
}
//+------------------------------------------------------------------+
//| Add the specified number of business days (Mon - Fri) to the |
//| given date, ignoring weekends. |
//+------------------------------------------------------------------+
datetime AddBusinessDays ( const datetime t , const int amount )
{
int step = amount < 0 ? -1 : 1 ;
int fullWeeks = amount / 5 ;
int remaining = MathAbs ( amount ) % 5 ;
datetime t_end = AddDays ( t , fullWeeks * 7 ) ;
// Loop over remaining business days
while ( remaining > 0 )
{
t_end = AddDays ( t_end , step ) ;
if ( IsWeekday ( t_end ) )
{
remaining - - ;
}
}
// If we add amount and land on a weekend, we add/reduce days
// to land on the next business day.
if ( amount ! = 0 )
{
if ( IsSaturday ( t_end ) )
t_end = AddDays ( t_end , ( step < 0 ? 2 : -1 ) ) ;
else if ( IsSunday ( t_end ) )
t_end = AddDays ( t_end , ( step < 0 ? 1 : -2 ) ) ;
}
return t_end ;
}
//+------------------------------------------------------------------+
//| Add the specified number of weeks to the given date. |
//+------------------------------------------------------------------+
datetime AddWeeks ( const datetime t , const int amount )
{
return t + ( ( datetime ) amount * WEEKSECS ) ;
}
//+------------------------------------------------------------------+
//| Add the specified number of months to the given date. |
//+------------------------------------------------------------------+
datetime AddMonths ( const datetime t , const int amount )
{
MqlDateTime dt ;
TimeToStructFast ( t , dt ) ;
int totalMonths = dt . year * 12 + ( dt . mon - 1 ) + amount ; // month is 1-based
dt . year = totalMonths / 12 ;
dt . mon = ( totalMonths % 12 ) + 1 ;
dt . day = MathMin ( dt . day , DaysInMonth ( dt . year , dt . mon ) ) ;
return StructToTimeFast ( dt ) ;
}
//+------------------------------------------------------------------+
//| Add the specified number of year quarters to the given date. |
//+------------------------------------------------------------------+
datetime AddQuarters ( const datetime t , const int amount )
{
return AddMonths ( t , amount * 3 ) ;
}
//+------------------------------------------------------------------+
//| Add the specified number of years to the given date. |
//+------------------------------------------------------------------+
datetime AddYears ( const datetime t , const int amount )
{
return AddMonths ( t , amount * 12 ) ;
}
//+------------------------------------------------------------------+
//| Returns a copy of the given datetime with the specified |
//| calendar period added. The period is expressed in calendar |
//| years, months, days, hours, minutes, and seconds. |
//| |
//| For periods returned by CalendarDifference(), |
//| AddPeriod(from, period) reconstructs the original end date. |
//+------------------------------------------------------------------+
2026-07-20 07:45:57 +03:00
datetime AddPeriod ( const datetime t ,
const MqlDateTime & calendarPeriod )
2026-07-18 23:27:05 +03:00
{
if ( calendarPeriod . year < 0 )
return -1 ;
if ( calendarPeriod . mon < 0 | | calendarPeriod . mon > 11 )
return -1 ;
if ( calendarPeriod . day < 0 )
return -1 ;
if ( calendarPeriod . hour < 0 | | calendarPeriod . hour > 23 )
return -1 ;
if ( calendarPeriod . min < 0 | | calendarPeriod . min > 59 )
return -1 ;
if ( calendarPeriod . sec < 0 | | calendarPeriod . sec > 59 )
return -1 ;
datetime res = t ;
res = AddMonths ( res , calendarPeriod . year * 12 + calendarPeriod . mon ) ;
res = AddDays ( res , calendarPeriod . day ) ;
res = AddHours ( res , calendarPeriod . hour ) ;
res = AddMinutes ( res , calendarPeriod . min ) ;
res = AddSeconds ( res , calendarPeriod . sec ) ;
return res ;
}
//+==================================================================+
//| Sub() Units |
//+==================================================================+
//+------------------------------------------------------------------+
//| Subtract the specified number of seconds from the given date. |
//+------------------------------------------------------------------+
datetime SubSeconds ( const datetime t , const int amount )
{
return AddSeconds ( t , - amount ) ;
}
//+------------------------------------------------------------------+
//| Subtract the specified number of minutes from the given date. |
//+------------------------------------------------------------------+
datetime SubMinutes ( const datetime t , const int amount )
{
return AddMinutes ( t , - amount ) ;
}
//+------------------------------------------------------------------+
//| Subtract the specified number of hours from the given date. |
//+------------------------------------------------------------------+
datetime SubHours ( const datetime t , const int amount )
{
return AddHours ( t , - amount ) ;
}
//+------------------------------------------------------------------+
//| Subtract the specified number of days from the given date. |
//+------------------------------------------------------------------+
datetime SubDays ( const datetime t , const int amount )
{
return AddDays ( t , - amount ) ;
}
//+------------------------------------------------------------------+
//| Subtract the specified number of business days (mon - fri) |
//| from the given date, ignoring weekends. |
//+------------------------------------------------------------------+
datetime SubBusinessDays ( const datetime t , const int amount )
{
return AddBusinessDays ( t , - amount ) ;
}
//+------------------------------------------------------------------+
//| Subtract the specified number of weeks from the given date. |
//+------------------------------------------------------------------+
datetime SubWeeks ( const datetime t , const int amount )
{
return AddWeeks ( t , - amount ) ;
}
//+------------------------------------------------------------------+
//| Subtract the specified number of months from the given date. |
//+------------------------------------------------------------------+
datetime SubMonths ( const datetime t , const int amount )
{
return AddMonths ( t , - amount ) ;
}
//+------------------------------------------------------------------+
//| Subtract the specified number of quarters from the given date. |
//+------------------------------------------------------------------+
datetime SubQuarters ( const datetime t , const int amount )
{
return AddQuarters ( t , - amount ) ;
}
//+------------------------------------------------------------------+
//| Subtract the specified number of years from the given date. |
//+------------------------------------------------------------------+
datetime SubYears ( const datetime t , const int amount )
{
return AddYears ( t , - amount ) ;
}
//+------------------------------------------------------------------+
//| Returns a copy of the given datetime with the specified |
//| calendar period subtracted. The period is expressed in calendar |
//| years, months, days, hours, minutes, and seconds. |
//| |
//| This function performs the inverse calendar operation of |
//| AddPeriod(), applying the period in reverse order. |
//| |
//| Note that calendar arithmetic is generally not invertible due |
//| to month-end clamping and varying month lengths. Therefore, for |
//| periods returned by CalendarDifference(), |
//| |
//| AddPeriod(from, period) == to |
//| |
//| is guaranteed, but |
//| |
//| SubPeriod(to, period) == from |
//| |
//| is not guaranteed in all cases. |
//+------------------------------------------------------------------+
2026-07-20 07:45:57 +03:00
datetime SubPeriod ( const datetime t ,
const MqlDateTime & calendarPeriod )
2026-07-18 23:27:05 +03:00
{
if ( calendarPeriod . year < 0 )
return -1 ;
if ( calendarPeriod . mon < 0 | | calendarPeriod . mon > 11 )
return -1 ;
if ( calendarPeriod . day < 0 )
return -1 ;
if ( calendarPeriod . hour < 0 | | calendarPeriod . hour > 23 )
return -1 ;
if ( calendarPeriod . min < 0 | | calendarPeriod . min > 59 )
return -1 ;
if ( calendarPeriod . sec < 0 | | calendarPeriod . sec > 59 )
return -1 ;
datetime res = t ;
res = AddSeconds ( res , - calendarPeriod . sec ) ;
res = AddMinutes ( res , - calendarPeriod . min ) ;
res = AddHours ( res , - calendarPeriod . hour ) ;
res = AddDays ( res , - calendarPeriod . day ) ;
res = AddMonths ( res , - ( calendarPeriod . year * 12 + calendarPeriod . mon ) ) ;
return res ;
}
//####################################################################
//# #
//# Difference #
//# #
//####################################################################
//+==================================================================+
//| DifferenceIn() Units |
//+==================================================================+
//+------------------------------------------------------------------+
//| Returns the difference in the calendar day numbers between two |
//| date/time values, ignoring the time-of-day components. |
//+------------------------------------------------------------------+
int DifferenceInCalendarDays ( const datetime from , const datetime to )
{
return DayIndex ( to ) - DayIndex ( from ) ;
}
//+------------------------------------------------------------------+
//| Returns the difference between the calendar week indices of |
//| two date/time values, ignoring the time-of-day components. |
2026-07-20 07:45:57 +03:00
//| The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
2026-07-18 23:27:05 +03:00
//+------------------------------------------------------------------+
int DifferenceInCalendarWeeks ( const datetime from , const datetime to )
{
return WeekIndex ( to ) - WeekIndex ( from ) ;
}
//+------------------------------------------------------------------+
//| Returns the difference in the calendar month numbers between |
//| two dates, ignoring the day and time components. |
//+------------------------------------------------------------------+
int DifferenceInCalendarMonths ( const datetime from , const datetime to )
{
return MonthIndex ( to ) - MonthIndex ( from ) ;
}
//+------------------------------------------------------------------+
//| Returns the difference in the calendar quarter numbers between |
//| two dates, ignoring the month, day, and time components. |
//+------------------------------------------------------------------+
int DifferenceInCalendarQuarters ( const datetime from , const datetime to )
{
return QuarterIndex ( to ) - QuarterIndex ( from ) ;
}
//+------------------------------------------------------------------+
//| Returns the difference in the calendar year numbers between |
//| two dates, ignoring the month, day, and time components. |
//+------------------------------------------------------------------+
int DifferenceInCalendarYears ( const datetime from , const datetime to )
{
return YearIndex ( to ) - YearIndex ( from ) ;
}
//+------------------------------------------------------------------+
//| Return the number of elapsed seconds between two dates. |
//+------------------------------------------------------------------+
long DifferenceInSeconds ( const datetime from , const datetime to )
{
return ( long ) ( to - from ) ;
}
//+------------------------------------------------------------------+
//| Return the number of elapsed minutes between two dates. |
//+------------------------------------------------------------------+
int DifferenceInMinutes ( const datetime from , const datetime to )
{
return ( int ) ( ( to - from ) / ( int ) MINSECS ) ;
}
//+------------------------------------------------------------------+
//| Return the number of elapsed hours between two dates. |
//+------------------------------------------------------------------+
int DifferenceInHours ( const datetime from , const datetime to )
{
return ( int ) ( ( to - from ) / ( int ) HOURSECS ) ;
}
//+------------------------------------------------------------------+
//| Return the number of elapsed 24-hour periods between two dates. |
//+------------------------------------------------------------------+
int DifferenceInDays ( const datetime from , const datetime to )
{
return ( int ) ( ( to - from ) / ( int ) DAYSECS ) ;
}
//+------------------------------------------------------------------+
//| Return the number of elapsed full weeks between two dates. |
//+------------------------------------------------------------------+
int DifferenceInWeeks ( const datetime from , const datetime to )
{
return ( int ) ( ( to - from ) / ( int ) WEEKSECS ) ;
}
//+------------------------------------------------------------------+
//| Return the number of elapsed full months between two dates. |
//+------------------------------------------------------------------+
// DifferenceInCale DifferenceInMont |
// | From | To | ndarMonths | hs |
// |-------------|-------------|----------------: |----------------: |
// | Jan 15 | Feb 14 | 1 | 0 |
// | Jan 15 | Feb 15 | 1 | 1 |
// | Jan 31 | Feb 28 | 1 | 1 |
// | Jan 31 | Mar 30 | 2 | 1 |
// | Jan 31 | Mar 31 | 2 | 2 |
// | Feb 29 2024 | Feb 27 2025 | 12 | 11 |
// | Feb 29 2024 | Feb 28 2025 | 12 | 12 |
//+------------------------------------------------------------------+
int DifferenceInMonths ( const datetime from , const datetime to )
{
if ( from > to )
return - DifferenceInMonths ( to , from ) ;
int months = DifferenceInCalendarMonths ( from , to ) ;
// https://github.com/dateutil/dateutil/blob/master/src/dateutil/relativedelta.py#L153
// add months back. If we've overshot our target, make an adjustment
return AddMonths ( from , months ) < = to ? months : months - 1 ;
}
//+------------------------------------------------------------------+
//| Return the number of elapsed full quarters between dates. |
//+------------------------------------------------------------------+
int DifferenceInQuarters ( const datetime from , const datetime to )
{
return DifferenceInMonths ( from , to ) / 3 ;
}
//+------------------------------------------------------------------+
//| Return the number of elapsed full years between two dates. |
//+------------------------------------------------------------------+
int DifferenceInYears ( const datetime from , const datetime to )
{
return DifferenceInMonths ( from , to ) / 12 ;
}
//+------------------------------------------------------------------+
//| Return the number of business days (Mon-Fri) in the half-open |
//| interval [from, to), excluding weekends. |
//+------------------------------------------------------------------+
int DifferenceInBusinessDays ( const datetime from , const datetime to )
{
int totalDays = DifferenceInCalendarDays ( from , to ) ;
int step = totalDays < 0 ? -1 : 1 ;
if ( totalDays = = 0 )
return 0 ;
int fullWeeks = totalDays / 7 ;
int business = fullWeeks * 5 ;
int remaining = MathAbs ( totalDays ) % 7 ;
datetime dt_temp = from ;
// Loop over remaining days not part of a full week
for ( int i = 0 ; i < remaining ; i + + )
{
if ( IsWeekday ( dt_temp ) )
{
business + = step ;
}
dt_temp = AddDays ( dt_temp , step ) ;
}
return business ;
}
//+------------------------------------------------------------------+
//| Return the number of weekend days in the half-open interval |
//| [from, to). The end date is not included. |
//+------------------------------------------------------------------+
int DifferenceInWeekendDays ( const datetime from , const datetime to )
{
return DifferenceInCalendarDays ( from , to )
- DifferenceInBusinessDays ( from , to ) ;
}
//+------------------------------------------------------------------+
//| Returns the calendar difference between two dates, broken down |
//| into years, months, days, hours, minutes, and seconds. |
//+------------------------------------------------------------------+
bool CalendarDifference ( datetime from , datetime to , MqlDateTime & diff )
{
const static MqlDateTime zero = { } ;
2026-07-20 07:45:57 +03:00
diff = zero ;
2026-07-18 23:27:05 +03:00
if ( from = = to )
return ( true ) ;
if ( from > to )
{
datetime temp = from ;
from = to ;
to = temp ;
}
const int totalMonths = DifferenceInMonths ( from , to ) ;
diff . year = totalMonths / 12 ;
diff . mon = totalMonths % 12 ;
from = AddMonths ( from , totalMonths ) ;
diff . day = DifferenceInDays ( from , to ) ;
from = AddDays ( from , diff . day ) ;
diff . hour = DifferenceInHours ( from , to ) ;
from = AddHours ( from , diff . hour ) ;
diff . min = DifferenceInMinutes ( from , to ) ;
from = AddMinutes ( from , diff . min ) ;
diff . sec = ( int ) DifferenceInSeconds ( from , to ) ;
return ( true ) ;
}
//+------------------------------------------------------------------+
//| Returns the calendar difference between two dates as a |
//| human-readable string (e.g. "2y 3m 5d 04:12:30"). |
//+------------------------------------------------------------------+
string CalendarDifferenceToString ( const datetime from , const datetime to )
{
if ( from = = to )
return " 0y 0m 0d 00:00:00 " ;
MqlDateTime diff ;
CalendarDifference ( from , to , diff ) ;
string result = " " ;
result + = IntegerToString ( diff . year ) ;
result + = " y " + IntegerToString ( diff . mon ) ;
result + = " m " + IntegerToString ( diff . day ) ;
result + = " d " + IntegerToString ( diff . hour , 2 , ' 0 ' ) ;
result + = " : " + IntegerToString ( diff . min , 2 , ' 0 ' ) ;
result + = " : " + IntegerToString ( diff . sec , 2 , ' 0 ' ) ;
return result ;
}
//####################################################################
//# #
//# Comparison and Checks #
//# #
//####################################################################
//+==================================================================+
//| Is() Checks |
//+==================================================================+
//+------------------------------------------------------------------+
//| Is the given date the first day of a month? |
//+------------------------------------------------------------------+
bool IsFirstDayOfMonth ( const datetime t )
{
return Day ( t ) = = 1 ;
}
//+------------------------------------------------------------------+
//| Is the given date the last day of a month? |
//+------------------------------------------------------------------+
bool IsLastDayOfMonth ( const datetime t )
{
return EndOfDay ( t ) = = EndOfMonth ( t ) ;
}
//+------------------------------------------------------------------+
//| Does the given date fall on a weekend? |
//+------------------------------------------------------------------+
bool IsWeekend ( const datetime t )
{
int dow = DayOfWeek ( t ) ;
return dow = = SATURDAY | | dow = = SUNDAY ;
}
//+------------------------------------------------------------------+
//| Does the given date fall on a business day? |
//+------------------------------------------------------------------+
bool IsWeekday ( const datetime t )
{
return ! IsWeekend ( t ) ;
}
//+------------------------------------------------------------------+
//| Is the given date Sunday? |
//+------------------------------------------------------------------+
bool IsSunday ( const datetime t )
{
return DayOfWeek ( t ) = = SUNDAY ;
}
//+------------------------------------------------------------------+
//| Is the given date Monday? |
//+------------------------------------------------------------------+
bool IsMonday ( const datetime t )
{
return DayOfWeek ( t ) = = MONDAY ;
}
//+------------------------------------------------------------------+
//| Is the given date Tuesday? |
//+------------------------------------------------------------------+
bool IsTuesday ( const datetime t )
{
return DayOfWeek ( t ) = = TUESDAY ;
}
//+------------------------------------------------------------------+
//| Is the given date Wednesday? |
//+------------------------------------------------------------------+
bool IsWednesday ( const datetime t )
{
return DayOfWeek ( t ) = = WEDNESDAY ;
}
//+------------------------------------------------------------------+
//| Is the given date Thursday? |
//+------------------------------------------------------------------+
bool IsThursday ( const datetime t )
{
return DayOfWeek ( t ) = = THURSDAY ;
}
//+------------------------------------------------------------------+
//| Is the given date Friday? |
//+------------------------------------------------------------------+
bool IsFriday ( const datetime t )
{
return DayOfWeek ( t ) = = FRIDAY ;
}
//+------------------------------------------------------------------+
//| Is the given date Saturday? |
//+------------------------------------------------------------------+
bool IsSaturday ( const datetime t )
{
return DayOfWeek ( t ) = = SATURDAY ;
}
//+==================================================================+
//| IsSame() Units |
//+==================================================================+
//+------------------------------------------------------------------+
2026-07-20 07:45:57 +03:00
//| Check whether both date/time values fall within the same minute. |
2026-07-18 23:27:05 +03:00
//+------------------------------------------------------------------+
bool IsSameMinute ( const datetime a , const datetime b )
{
return MinuteIndex ( a ) = = MinuteIndex ( b ) ;
}
//+------------------------------------------------------------------+
2026-07-20 07:45:57 +03:00
//| Check whether both date/time values fall within the same hour. |
2026-07-18 23:27:05 +03:00
//+------------------------------------------------------------------+
bool IsSameHour ( const datetime a , const datetime b )
{
return HourIndex ( a ) = = HourIndex ( b ) ;
}
//+------------------------------------------------------------------+
2026-07-20 07:45:57 +03:00
//| Check whether both date/time values fall within the same day. |
2026-07-18 23:27:05 +03:00
//+------------------------------------------------------------------+
bool IsSameDay ( const datetime a , const datetime b )
{
return DayIndex ( a ) = = DayIndex ( b ) ;
}
//+------------------------------------------------------------------+
2026-07-20 07:45:57 +03:00
//| Check whether both date/time values fall within the same week. |
//| The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
2026-07-18 23:27:05 +03:00
//+------------------------------------------------------------------+
bool IsSameWeek ( const datetime a , const datetime b )
{
return WeekIndex ( a ) = = WeekIndex ( b ) ;
}
//+------------------------------------------------------------------+
2026-07-20 07:45:57 +03:00
//| Check whether both date/time values fall within the same month. |
2026-07-18 23:27:05 +03:00
//+------------------------------------------------------------------+
bool IsSameMonth ( const datetime a , const datetime b )
{
return MonthIndex ( a ) = = MonthIndex ( b ) ;
}
//+------------------------------------------------------------------+
2026-07-20 07:45:57 +03:00
//| Check whether both date/time values fall within the same quarter |
2026-07-18 23:27:05 +03:00
//+------------------------------------------------------------------+
bool IsSameQuarter ( const datetime a , const datetime b )
{
return QuarterIndex ( a ) = = QuarterIndex ( b ) ;
}
//+------------------------------------------------------------------+
2026-07-20 07:45:57 +03:00
//| Check whether both date/time values fall within the same year. |
2026-07-18 23:27:05 +03:00
//+------------------------------------------------------------------+
bool IsSameYear ( const datetime a , const datetime b )
{
return YearIndex ( a ) = = YearIndex ( b ) ;
}
//+==================================================================+
//| IsCurrent() Units |
//+==================================================================+
//+------------------------------------------------------------------+
//| Is the given date in the same minute as the current server time |
//+------------------------------------------------------------------+
bool IsCurrentMinute ( const datetime t )
{
return IsSameMinute ( t , TimeTradeServer ( ) ) ;
}
//+------------------------------------------------------------------+
//| Is the given date in the same hour as the current server time |
//+------------------------------------------------------------------+
bool IsCurrentHour ( const datetime t )
{
return IsSameHour ( t , TimeTradeServer ( ) ) ;
}
//+------------------------------------------------------------------+
//| Is the given date in the same week as the current server time |
2026-07-20 07:45:57 +03:00
//| The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
2026-07-18 23:27:05 +03:00
//+------------------------------------------------------------------+
bool IsCurrentWeek ( const datetime t )
{
return IsSameWeek ( t , TimeTradeServer ( ) ) ;
}
//+------------------------------------------------------------------+
//| Is the given date in the same month as the current server time |
//+------------------------------------------------------------------+
bool IsCurrentMonth ( const datetime t )
{
return IsSameMonth ( t , TimeTradeServer ( ) ) ;
}
//+------------------------------------------------------------------+
//| Is this date in the same quarter (and year) as the server ? |
//+------------------------------------------------------------------+
bool IsCurrentQuarter ( const datetime t )
{
return IsSameQuarter ( t , TimeTradeServer ( ) ) ;
}
//+------------------------------------------------------------------+
//| Is the given date in the same year as the current server time |
//+------------------------------------------------------------------+
bool IsCurrentYear ( const datetime t )
{
return IsSameYear ( t , TimeTradeServer ( ) ) ;
}
//+------------------------------------------------------------------+
//| Is the given date today on the trade server |
//+------------------------------------------------------------------+
bool IsToday ( const datetime t )
{
return IsSameDay ( t , TimeTradeServer ( ) ) ;
}
//+------------------------------------------------------------------+
//| Is the given date tomorrow on the trade server |
//+------------------------------------------------------------------+
bool IsTomorrow ( const datetime t )
{
return IsSameDay ( t , AddDays ( TimeTradeServer ( ) , 1 ) ) ;
}
//+------------------------------------------------------------------+
//| Is the given date yesterday on the trade server |
//+------------------------------------------------------------------+
bool IsYesterday ( const datetime t )
{
return IsSameDay ( t , SubDays ( TimeTradeServer ( ) , 1 ) ) ;
}
//+==================================================================+
//| Session() Checks |
//+==================================================================+
//+------------------------------------------------------------------+
//| Returns true if the specified datetime falls within the |
//| specified recurring daily session [start, end). |
//| |
//| The session repeats every day at the same start and end times. |
//| |
//| If start <= end, the session occurs within a single day. |
//| If start > end, the session spans midnight into the next day. |
//+------------------------------------------------------------------+
bool IsInSession ( const datetime t ,
const int startHour ,
const int startMinute ,
const int endHour ,
const int endMinute )
{
if ( startHour < 0 | | startHour > 23 | |
startMinute < 0 | | startMinute > 59 | |
endHour < 0 | | endHour > 23 | |
endMinute < 0 | | endMinute > 59 )
return false ;
const int current = SecondsSinceMidnight ( t ) ;
const int start = startHour * HOURSECS + startMinute * MINSECS ;
const int end = endHour * HOURSECS + endMinute * MINSECS ;
return ( start < = end )
? ( current > = start & & current < end )
: ( current > = start | | current < end ) ;
}
//+------------------------------------------------------------------+
//| Returns true if the current server time falls within the |
//| specified recurring daily session [start, end). |
//+------------------------------------------------------------------+
bool IsInSession ( const int startHour ,
const int startMinute ,
const int endHour ,
const int endMinute )
{
return IsInSession (
TimeTradeServer ( ) ,
startHour ,
startMinute ,
endHour ,
endMinute ) ;
}
//+------------------------------------------------------------------+
//| Returns true if the current server time falls within the |
//| specified recurring daily session [start, end). |
//| |
//| Time strings must be in "HH:MM" or "HH:MM:SS" format. |
//+------------------------------------------------------------------+
bool IsInSession ( const string startTime ,
const string endTime )
{
const datetime start = DateFromString ( startTime ) ;
const datetime end = DateFromString ( endTime ) ;
return IsInSession (
TimeTradeServer ( ) ,
Hour ( start ) ,
Minute ( start ) ,
Hour ( end ) ,
Minute ( end ) ) ;
}
2026-07-20 07:45:57 +03:00
//+------------------------------------------------------------------+
//| Returns true if two half-open intervals [aStart, aEnd) and |
//| [bStart, bEnd) overlap. |
//| |
//| If an overlap exists, the overlapping interval is written to |
//| overlapStart and overlapEnd. |
//| |
//| If the intervals do not overlap, or either interval is invalid |
//| (end < start), returns false and sets both output values to 0. |
//+------------------------------------------------------------------+
bool SessionOverlap ( const datetime aStart ,
const datetime aEnd ,
const datetime bStart ,
const datetime bEnd ,
datetime & overlapStart ,
datetime & overlapEnd )
{
overlapStart = 0 ;
overlapEnd = 0 ;
if ( aEnd < aStart | | bEnd < bStart )
return false ;
const datetime s = MathMax ( aStart , bStart ) ;
const datetime e = MathMin ( aEnd , bEnd ) ;
if ( s > = e )
return false ;
overlapStart = s ;
overlapEnd = e ;
return true ;
}
2026-07-18 23:27:05 +03:00
//+==================================================================+
//| Misc |
//+==================================================================+
//+------------------------------------------------------------------+
//| Checks whether the given year is a leap year or not |
//+------------------------------------------------------------------+
bool IsLeapYear ( const int year )
{
//return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
// From: https://www.youtube.com/watch?v=0s9F4QWAl-E&t=1790s
return ( year & ( ( year % 100 ! = 0 ) ? 3 : 15 ) ) = = 0 ;
}
//+------------------------------------------------------------------+
2026-07-20 07:45:57 +03:00
//| Returns the number of days in a month of the given year. |
2026-07-18 23:27:05 +03:00
//+------------------------------------------------------------------+
int DaysInMonth ( const int year , const int month )
{
//const int dim[13] = {0, 31, (IsLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
//return dim[month % 13];
// From: https://www.youtube.com/watch?v=0s9F4QWAl-E&t=1790s
if ( month = = 2 )
return 28 + IsLeapYear ( year ) ;
return 30 | ( month ^ ( month > > 3 ) ) ;
}
//+------------------------------------------------------------------+
2026-07-20 07:45:57 +03:00
//| Returns the number of days in a given year. |
2026-07-18 23:27:05 +03:00
//+------------------------------------------------------------------+
2026-07-20 07:45:57 +03:00
int DaysInYear ( const int year )
2026-07-18 23:27:05 +03:00
{
2026-07-20 07:45:57 +03:00
return 365 + IsLeapYear ( year ) ;
}
//+==================================================================+
//| Week Utilities |
//+==================================================================+
2026-07-18 23:27:05 +03:00
2026-07-20 07:45:57 +03:00
//+------------------------------------------------------------------+
//| Returns the calendar week number of the month (1...6). |
//| |
//| Week 1 is the first calendar week containing the first day of |
//| the month. The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
//+------------------------------------------------------------------+
int WeekOfMonth ( const datetime t )
{
return WeekIndex ( t ) - WeekIndex ( StartOfMonth ( t ) ) + 1 ;
2026-07-18 23:27:05 +03:00
}
//+------------------------------------------------------------------+
2026-07-20 07:45:57 +03:00
//| Returns the calendar week number of the year (1...54). |
//| |
//| Week 1 is the first calendar week containing January 1st. |
//| The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
//+------------------------------------------------------------------+
int WeekOfYear ( const datetime t )
{
return WeekIndex ( t ) - WeekIndex ( StartOfYear ( t ) ) + 1 ;
}
//+------------------------------------------------------------------+
//| Returns the number of calendar weeks spanned by the specified |
//| month. |
//| The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
2026-07-18 23:27:05 +03:00
//+------------------------------------------------------------------+
int WeeksInMonth ( const int year , const int month )
{
const datetime first = DateFrom ( year , month , 1 ) ;
2026-07-20 07:45:57 +03:00
return WeekIndex ( EndOfMonth ( first ) ) - WeekIndex ( first ) + 1 ;
2026-07-18 23:27:05 +03:00
}
2026-07-20 07:45:57 +03:00
//+------------------------------------------------------------------+
//| Returns the number of calendar weeks spanned by the specified |
//| year. |
//| The result depends on TIMEUTILS_FIRST_DAY_OF_WEEK. |
//+------------------------------------------------------------------+
int WeeksInYear ( const int year )
{
const datetime first = DateFrom ( year , 1 , 1 ) ;
return WeekIndex ( EndOfYear ( first ) ) - WeekIndex ( first ) + 1 ;
}
2026-07-18 23:27:05 +03:00
//####################################################################
//# #
//# Format & Display #
//# #
//####################################################################
//+==================================================================+
//| Formating Time to String |
//+==================================================================+
//+------------------------------------------------------------------+
//| Format time with the weekday name => "Wed, 2023.02.14 01:59" |
//+------------------------------------------------------------------+
string t2s ( const datetime t , const int mode = TIME_DATE | TIME_MINUTES )
{
const static string days [ 7 ] = { " Sun " , " Mon " , " Tue " , " Wed " , " Thu " , " Fri " , " Sat " } ;
return days [ DayOfWeek ( t ) ] + " , " + TimeToString ( t , mode ) ;
}
//+------------------------------------------------------------------+
//| Format the time in seconds to a string (like 2d 14:58:04) |
//+------------------------------------------------------------------+
string SecondsToString ( const int seconds )
{
const int days = ( int ) ( seconds / DAYSECS ) ;
const string d = days ? ( string ) days + " d " : " " ;
return d + TimeToString ( seconds , TIME_SECONDS ) ;
}
//+------------------------------------------------------------------+
//| Return the month name for a month number [1-12] |
//+------------------------------------------------------------------+
string MonthName ( const int monthNo )
{
const static string months [ 12 ] = { " January " , " February " , " March " , " April " , " May " , " June " , " July " , " August " , " September " , " October " , " November " , " December " } ;
return ( monthNo < 1 | | monthNo > 12 )
? " Undefined monthNo " + ( string ) monthNo : months [ monthNo - 1 ] ;
}
//+------------------------------------------------------------------+
//| Return the weekday name for a weekday number [0-6] |
//+------------------------------------------------------------------+
string DayName ( const int dayNo )
{
const static string days [ 7 ] = { " Sunday " , " Monday " , " Tuesday " , " Wednesday " , " Thursday " , " Friday " , " Saturday " } ;
return ( dayNo < 0 | | dayNo > 6 )
? " Undefined dayNo " + ( string ) dayNo : days [ dayNo ] ;
}
//+------------------------------------------------------------------+
//| Get the formatted time according to the passed string of tokens. |
//| List of all available formats: |
//| Format Output Description |
//| ------ ---------------- ------------------------------------- |
//| YY 18 Two-digit year |
//| YYYY 2018 Four-digit year |
//| M 1-12 The month, beginning at 1 |
//| MM 01-12 The month, 2-digits |
//| MMM Jan-Dec The abbreviated month name, 3-letters |
//| MMMM January-December The full month name |
//| D 1-31 The day of the month |
//| DD 01-31 The day of the month, 2-digits |
//| DDD Sun-Sat The short name of the day of the week |
//| DDDD Sunday-Saturday The name of the day of the week |
//| h 0-23 The hour |
//| hh 00-23 The hour, 2-digits |
//| H 1-12 The hour, 12-hour clock |
//| HH 01-12 The hour, 12-hour clock, 2-digits |
//| m 0-59 The minute |
//| mm 00-59 The minute, 2-digits |
//| s 0-59 The second |
//| ss 00-59 The second, 2-digits |
//| A AM PM |
//| a am pm |
//+------------------------------------------------------------------+
//| Sample formats: |
//| "YYYY.MM.DD hh:mm" // "2024.12.08 22:05" (default) |
//| "DDD, YYYY.MM.DD hh:mm:ss" // "Sun, 2024.12.08 22:05:21" |
//| "D MMMM YYYY, HH:mm a" // "8 December 2024, 10:05 pm" |
//| "DD/MM/YYYY" // "08/12/2024" |
//+------------------------------------------------------------------+
2026-07-20 07:45:57 +03:00
string TimeFormat ( const datetime t ,
const string format = " YYYY.MM.DD hh:mm " ) {
2026-07-18 23:27:05 +03:00
string retVal ;
MqlDateTime dt_struct ;
if ( format = = " " | | StringLen ( format ) = = 0 ) {
Print ( " invalid format " ) ;
return " " ;
}
if ( TimeToStructFast ( t , dt_struct ) = = false ) {
Print ( " TimeToStructFast() failed. Error " , GetLastError ( ) ) ;
return " " ;
}
string token = " " ;
int index_char = 0 ;
while ( index_char < StringLen ( format ) ) {
// get next token from format string
do {
token + = StringSubstr ( format , index_char , 1 ) ;
index_char + + ;
} while ( index_char < StringLen ( format ) & & format [ index_char ] = = token [ StringLen ( token ) - 1 ] ) ;
// format datetime value based on format token
if ( token = = " YYYY " ) {
retVal + = IntegerToString ( dt_struct . year ) ;
} else if ( token = = " YY " ) {
retVal + = IntegerToString ( dt_struct . year % 100 , 2 , ' 0 ' ) ;
} else if ( token = = " MMMM " ) {
retVal + = MonthName ( dt_struct . mon ) ;
} else if ( token = = " MMM " ) {
retVal + = StringSubstr ( MonthName ( dt_struct . mon ) , 0 , 3 ) ;
} else if ( token = = " MM " ) {
retVal + = IntegerToString ( dt_struct . mon , 2 , ' 0 ' ) ;
} else if ( token = = " M " ) {
retVal + = IntegerToString ( dt_struct . mon ) ;
} else if ( token = = " DDDD " ) {
retVal + = DayName ( dt_struct . day_of_week ) ;
} else if ( token = = " DDD " ) {
retVal + = StringSubstr ( DayName ( dt_struct . day_of_week ) , 0 , 3 ) ;
} else if ( token = = " DD " ) {
retVal + = IntegerToString ( dt_struct . day , 2 , ' 0 ' ) ;
} else if ( token = = " D " ) {
retVal + = IntegerToString ( dt_struct . day ) ;
} else if ( token = = " hh " ) {
retVal + = IntegerToString ( dt_struct . hour , 2 , ' 0 ' ) ;
} else if ( token = = " h " ) {
retVal + = IntegerToString ( dt_struct . hour ) ;
} else if ( token = = " HH " ) {
retVal + = IntegerToString ( ( bool ) ( dt_struct . hour % 12 ) ? dt_struct . hour % 12 : 12 , 2 , ' 0 ' ) ;
} else if ( token = = " H " ) {
retVal + = IntegerToString ( ( bool ) ( dt_struct . hour % 12 ) ? dt_struct . hour % 12 : 12 ) ;
} else if ( token = = " mm " ) {
retVal + = IntegerToString ( dt_struct . min , 2 , ' 0 ' ) ;
} else if ( token = = " m " ) {
retVal + = IntegerToString ( dt_struct . min ) ;
} else if ( token = = " ss " ) {
retVal + = IntegerToString ( dt_struct . sec , 2 , ' 0 ' ) ;
} else if ( token = = " s " ) {
retVal + = IntegerToString ( dt_struct . sec ) ;
} else if ( token = = " A " ) {
retVal + = dt_struct . hour < 12 ? " AM " : " PM " ;
} else if ( token = = " a " ) {
retVal + = dt_struct . hour < 12 ? " am " : " pm " ;
} else { // if there are any non-matching characters left in format string
retVal + = token ;
}
token = " " ;
}
return ( retVal ) ;
}
# undef DAYS_PER_4_YEARS
# undef DAYS_PER_400_YEARS
# undef DAYS_TO_1970
# undef MARCH1_BASED_DOY
# endif // #ifndef TIMEUTILS_UNIQUE_HEADER_ID_H
//+------------------------------------------------------------------+
/*
example code :
# include "TimeUtils.mqh"
void OnStart ( )
{
datetime t = TimeLocal ( ) ;
Print ( t2s ( t , TIME_DATE | TIME_SECONDS ) ) ; // Formats time with the weekday name
Print ( Year ( t ) ) ;
Print ( Month ( t ) ) ;
Print ( Day ( t ) ) ;
Print ( Hour ( t ) ) ;
Print ( Minute ( t ) ) ;
Print ( Second ( t ) ) ;
Print ( DayOfWeek ( t ) ) ;
Print ( DayOfYear ( t ) ) ;
MqlDateTime dt [ 1 ] = { } ;
TimeToStructFast ( t , dt [ 0 ] ) ;
ArrayPrint ( dt ) ;
dt [ 0 ] . year + = 1 ;
Print ( StructToTimeFast ( dt [ 0 ] ) ) ;
}
example output :
Tue , 2024.12 .03 20 : 46 : 58
2024
12
3
20
46
58
2
337
[ year ] [ mon ] [ day ] [ hour ] [ min ] [ sec ] [ day_of_week ] [ day_of_year ]
[ 0 ] 2024 12 3 20 46 58 2 337
2025.12 .03 20 : 46 : 58
* /
//+------------------------------------------------------------------+