//+------------------------------------------------------------------+ //| TimeUtils.mqh | //| Copyright © 2024, Amr Ali | //| https://www.mql5.com/en/users/amrali | //+------------------------------------------------------------------+ #property copyright "Copyright © 2024, Amr Ali" #property link "https://www.mql5.com/en/users/amrali" #property version "1.55" #property description "High-performance functions for dealing with time." // Updates: // 2024.12.03 - v.1.10 : Initial release. // 2024.12.05 - v.1.15 : Added functions for business days and for Nth() weekday of the month. Optimized calculations in DaysInMonth() function. // 2024.12.09 - v.1.20 : Added TimeFormat() function to format the time according to the passed string of tokens. // 2024.12.09 - v.1.25 : Optimized calculations in TimeToStructFast() function. // 2024.12.10 - v.1.30 : Optimized TimeFormat(), StartOfYear() and EndOfYear() functions. Updated descriptions of some functions. // 2024.12.15 - v.1.35 : Optimized GetNthWeekdayInYearMonth() function. // 2024.12.18 - v.1.40 : Added IsCurrentXXX(), IsToday(), IsTomorrow() and IsYesterday() functions. // 2024.12.19 - v.1.45 : Optimized AddMonths() and GetNthWeekdayInYearMonth() functions. // 2024.12.20 - v.1.50 : More code clean-up. // 2024.12.21 - v.1.55 : Simplified calculations in AddMonths(): replaced the complex logic of adjusting months and years with a simpler total months calculation. #ifdef __MQL4__ #property strict #endif #ifndef TIMEUTILS_UNIQUE_HEADER_ID_H #define TIMEUTILS_UNIQUE_HEADER_ID_H //#define TIMEUTILS_PERFORMANCE_MODE //+------------------------------------------------------------------+ //| Performance mode | //+------------------------------------------------------------------+ #ifdef TIMEUTILS_PERFORMANCE_MODE // replace calls to MQL's built-in functions via macro substitutions. #define TimeToStruct TimeToStructFast // 5x faster than TimeToStruct #define StructToTime CreateDateTime // 30x faster than StructToTime #endif //+==================================================================+ //| Create datetime From Components | //+==================================================================+ // datetime CreateDateTime( // 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 // ) // datetime CreateDateTime(MqlDateTime& dt_struct); // fast alternative to StructToTime() //+==================================================================+ //| Break datetime To Components | //+==================================================================+ // bool TimeToStructFast( // datetime dt, // Date value to convert // MqlDateTime& dt_struct // structure for the adoption of values // ) //+==================================================================+ //| Extract Components of datetime: Sunday, yyyy.mm.dd hh:mm:ss | //| Get() Units | //+==================================================================+ // int GetSecond(datetime t) // int GetMinute(datetime t) // int GetHour(datetime t) // int GetDay(datetime t) // int GetMonth(datetime t) // int GetYear(datetime t) //+==================================================================+ //| Day() Number | //+==================================================================+ // int DayOfWeek(datetime t) // int DayOfYear(datetime t) // int DayIndex(datetime t) //+==================================================================+ //| Week() Number | //+==================================================================+ // int WeekOfMonth(const datetime t, bool StartsOnMonday = false) // int WeekOfYear(const datetime t, bool StartsOnMonday = false) // int WeekIndex(datetime t, bool StartsOnMonday = false) //+==================================================================+ //| StartOf() Units | //+==================================================================+ // datetime StartOfMinute(datetime t) // datetime StartOfHour(datetime t) // datetime StartOfDay(datetime t) // datetime StartOfWeek(datetime t, bool StartsOnMonday = false) // datetime StartOfMonth(datetime t) // datetime StartOfYear(datetime t) //+==================================================================+ //| EndOf() Units | //+==================================================================+ // datetime EndOfMinute(datetime t) // datetime EndOfHour(datetime t) // datetime EndOfDay(datetime t) // datetime EndOfWeek(datetime t, bool StartsOnMonday = false) // datetime EndOfMonth(datetime t) // datetime EndOfYear(datetime t) //+==================================================================+ //| SecsElapsedOf() Units | //+==================================================================+ // int SecsElapsedOfMinute(datetime t) // int SecsElapsedOfHour(datetime t) // int SecsElapsedOfDay(datetime t) // int SecsElapsedOfWeek(datetime t, bool StartsOnMonday = false) // int SecsElapsedOfMonth(datetime t) // int SecsElapsedOfYear(datetime t) //+==================================================================+ //| RoundTo() / Nearest() Units | //+==================================================================+ // datetime RoundToMinute(datetime t) // datetime RoundToHour(datetime t) // datetime RoundToDay(datetime t) // datetime RoundToWeek(datetime t, bool StartsOnMonday = false) //+==================================================================+ //| CeilTo() / Next() Units | //+==================================================================+ // datetime CeilToMinute(datetime t) // datetime CeilToHour(datetime t) // datetime CeilToDay(datetime t) // datetime CeilToWeek(datetime t, bool StartsOnMonday = false) //+==================================================================+ //| Next() Weekday | //+==================================================================+ // datetime NextWeekday(datetime t, ENUM_DAY_OF_WEEK weekday = SUNDAY) // datetime NextSunday(datetime t) // datetime NextMonday(datetime t) // datetime NextTuesday(datetime t) // datetime NextWednesday(datetime t) // datetime NextThursday(datetime t) // datetime NextFriday(datetime t) // datetime NextSaturday(datetime t) //+==================================================================+ //| Previous() Weekday | //+==================================================================+ // datetime PreviousWeekday(datetime t, ENUM_DAY_OF_WEEK weekday = SUNDAY) // datetime PreviousSunday(datetime t) // datetime PreviousMonday(datetime t) // datetime PreviousTuesday(datetime t) // datetime PreviousWednesday(datetime t) // datetime PreviousThursday(datetime t) // datetime PreviousFriday(datetime t) // datetime PreviousSaturday(datetime t) //+==================================================================+ //| Nth() Weekday Of The Month | //+==================================================================+ // datetime FirstWeekdayOfTheMonth(datetime t, ENUM_DAY_OF_WEEK weekday = SUNDAY) // datetime LastWeekdayOfTheMonth(datetime t, ENUM_DAY_OF_WEEK weekday = SUNDAY) // datetime NthWeekdayOfTheMonth(datetime t, int Nth, ENUM_DAY_OF_WEEK weekday = SUNDAY) //+==================================================================+ //| Add() Units | //+==================================================================+ // datetime AddSeconds(datetime t, int amount) // datetime AddMinutes(datetime t, int amount) // datetime AddHours(datetime t, int amount) // datetime AddDays(datetime t, int amount) // datetime AddBusinessDays(datetime t, int amount) // datetime AddWeeks(datetime t, int amount) // datetime AddMonths(datetime t, int amount) // datetime AddYears(datetime t, int amount) //+==================================================================+ //| Sub() Units | //+==================================================================+ // datetime SubSeconds(datetime t, int amount) // datetime SubMinutes(datetime t, int amount) // datetime SubHours(datetime t, int amount) // datetime SubDays(datetime t, int amount) // datetime SubBusinessDays(datetime t, int amount) // datetime SubWeeks(datetime t, int amount) // datetime SubMonths(datetime t, int amount) // datetime SubYears(datetime t, int amount) //+==================================================================+ //| DifferenceIn() Units | //+==================================================================+ // int DifferenceInCalendarDays(datetime beginTime, datetime endTime) // int DifferenceInBusinessDays(datetime beginTime, datetime endTime) // int DifferenceInCalendarWeeks(datetime beginTime, datetime endTime, bool StartsOnMonday = false) // int DifferenceInCalendarMonths(datetime beginTime, datetime endTime) //+==================================================================+ //| IsSame() Units | //+==================================================================+ // bool IsSameMinute(datetime t1, datetime t2) // bool IsSameHour(datetime t1, datetime t2) // bool IsSameDay(datetime t1, datetime t2) // bool IsSameWeek(datetime t1, datetime t2, bool StartsOnMonday = false) // bool IsSameMonth(datetime t1, datetime t2) // bool IsSameYear(datetime t1, datetime t2) //+==================================================================+ //| IsCurrent() Units | //+==================================================================+ // bool IsCurrentMinute(datetime t) // bool IsCurrentHour(datetime t) // bool IsCurrentWeek(datetime t, bool StartsOnMonday = false) // bool IsCurrentMonth(datetime t) // bool IsCurrentYear(datetime t) // bool IsToday(datetime t) // bool IsTomorrow(datetime t) // bool IsYesterday(datetime t) //+==================================================================+ //| Misc | //+==================================================================+ // bool IsLeapYear(int year) // int DaysInMonth(int year, int month) // datetime GetNthWeekdayInYearMonth(iYear, iMonth, Nth, weekday = SUNDAY) // datetime GetNthSundayInYearMonth(iYear, iMonth, Nth) //+==================================================================+ //| Formating Time to String | //+==================================================================+ // string t2s(datetime t, const int mode = TIME_DATE | TIME_MINUTES) // string SecondsToString(int seconds) // string TimeFormat(datetime t, string format = "YYYY.MM.DD hh:mm") //+------------------------------------------------------------------+ //| Time unit constants | //+------------------------------------------------------------------+ #define MINSECS 60 #define HOURSECS 3600 #define DAYSECS 86400 #define WEEKSECS 604800 #define YEARSECS 31536000 #define DAYSIN4YEARS 1461 // = (4 * 365) + 1 //+==================================================================+ //| Create datetime From Components | //+==================================================================+ //+------------------------------------------------------------------+ //| Create a datetime value from the given year, month and day. | //| https://www.mql5.com/en/forum/393227/page254#comment_53104384 | //| Limit: Year must be <= 2100 | //+------------------------------------------------------------------+ datetime CreateDateTime( 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 StructToTime(dt); static const uint Months[] = {0, 11512676, 11512180, 11511728, 11511232, 11510750, 11510256, 11509774, 11509280, 11508781, 11508302, 11507806, 11507326 }; return (((year * 5844 - Months[mon]) >> 4) + day - 1) * DAYSECS + (hour * HOURSECS + min * MINSECS + sec); } //+------------------------------------------------------------------+ //| The equivalent of MQL's built-in 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 CreateDateTime(MqlDateTime& dt_struct) { return CreateDateTime(dt_struct.year, dt_struct.mon, dt_struct.day, dt_struct.hour, dt_struct.min, dt_struct.sec); } //+==================================================================+ //| Break datetime To Components | //+==================================================================+ //+------------------------------------------------------------------+ //| The equivalent of MQL's built-in TimeToStruct() function. | //| Converts a value of datetime type (number of seconds | //| since 01.01.1970) into a structure variable MqlDateTime. | //+------------------------------------------------------------------+ bool TimeToStructFast(datetime dt, MqlDateTime& dt_struct) { static const int Months[13] = {0, -1, 30, 58, 89, 119, 150, 180, 211,242, 272, 303, 333}; static int last_days = -1; static MqlDateTime last_result = {}; const uint t = (uint)dt; const int n = (int)(t / DAYSECS); if(last_days != n) { int tn = (n << 2) + 2; int dow = (n + 4) % 7; int doy = (tn % DAYSIN4YEARS) / 4; int year = (tn / DAYSIN4YEARS) + 1970; // to 2100 int isleap = ((year & 3) == 0); int leapadj = ((doy < (isleap + 59)) ? 0 : (2 - isleap)); //int mon = ((((doy + leapadj) * 12) + 373) / 367); int mon = ((((doy + leapadj) * 67) + 2075) >> 11); int day = doy - Months[mon] - (isleap && doy > 59); last_days = n; last_result.year = year; last_result.mon = mon; last_result.day = day; last_result.day_of_week = dow; last_result.day_of_year = doy; } dt_struct = last_result; dt_struct.hour= (int)(t / HOURSECS) % 24; dt_struct.min = (int)(t / MINSECS) % MINSECS; dt_struct.sec = (int)(t % MINSECS); return (true); } //+==================================================================+ //| Extract Components of datetime: Sunday, yyyy.mm.dd hh:mm:ss | //| Get() Units | //+==================================================================+ //+------------------------------------------------------------------+ //| Return seconds of minute as integer (0..59) | //+------------------------------------------------------------------+ int GetSecond(const datetime t) { return (int)((uint)t % MINSECS); } //+------------------------------------------------------------------+ //| Return minutes of hour as integer (0..59) | //+------------------------------------------------------------------+ int GetMinute(const datetime t) { return (int)((uint)t / MINSECS) % MINSECS; } //+------------------------------------------------------------------+ //| Return hour of day as integer (0..23) | //+------------------------------------------------------------------+ int GetHour(const datetime t) { return (int)((uint)t / HOURSECS) % 24; } //+------------------------------------------------------------------+ //| Return day of month as integer (1..31) | //+------------------------------------------------------------------+ int GetDay(const datetime t) { MqlDateTime st; TimeToStruct(t, st); return(st.day); } //+------------------------------------------------------------------+ //| Return the month number as integer (1..12) | //+------------------------------------------------------------------+ int GetMonth(const datetime t) { MqlDateTime st; TimeToStruct(t, st); return(st.mon); } //+------------------------------------------------------------------+ //| Returns year as integer of the given date (e.g., 2019) | //| https://www.mql5.com/ru/forum/170952/page251#comment_53071746 | //+------------------------------------------------------------------+ int GetYear(const datetime t) { return (int)(((uint)t / DAYSECS * 4 + 2) / DAYSIN4YEARS) + 1970; } //+==================================================================+ //| Day() Number | //+==================================================================+ //+------------------------------------------------------------------+ //| Day of the week as integer (0-Sunday, 1-Monday, ... ,6-Saturday) | //+------------------------------------------------------------------+ int DayOfWeek(const datetime t) { return (int)((uint)t / DAYSECS + THURSDAY) % 7; // 1 Jan 1970 is Thursday } //+------------------------------------------------------------------+ //| Get the zero-based day of the year as integer (0...365) | //+------------------------------------------------------------------+ int DayOfYear(const datetime t) { return (int)(((uint)t / DAYSECS * 4 + 2) % DAYSIN4YEARS) / 4; } //+------------------------------------------------------------------+ //| Returns the zero-based absolute day number after 1 jan 1970 | //+------------------------------------------------------------------+ //---This function can be useful in indicators for determining 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); } //+==================================================================+ //| Week() Number | //+==================================================================+ //+------------------------------------------------------------------+ //| Get the week number of the month as integer (1...6) | //| By default, the week starts on Sunday, unless superseded. | //+------------------------------------------------------------------+ int WeekOfMonth(const datetime t, const bool StartsOnMonday = false) { int delta = (int)StartsOnMonday - DayOfWeek(StartOfMonth(t)); if (delta <= 0) delta += 7; return ((GetDay(t) - delta + 6) / 7) + 1; } //+------------------------------------------------------------------+ //| Get the week number of the year as integer (1...53) | //| By default, the week starts on Sunday, unless superseded. | //+------------------------------------------------------------------+ int WeekOfYear(const datetime t, const bool StartsOnMonday = false) { int delta = (int)StartsOnMonday - DayOfWeek(StartOfYear(t)); if (delta <= 0) delta += 7; return ((DayOfYear(t) - delta + 7) / 7) + 1; } //+------------------------------------------------------------------+ //| Returns the zero-based absolute week number since 1 Jan 1970 | //| By default, the week starts on Sunday, unless superseded. | //+------------------------------------------------------------------+ int WeekIndex(const datetime t, const bool StartsOnMonday = false) { int offset = (THURSDAY - StartsOnMonday) * DAYSECS; // 1 Jan 1970 is Thursday return (int)((t + offset) / WEEKSECS); } //+==================================================================+ //| StartOf() 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); } //+------------------------------------------------------------------+ //| Return the start of a week for the given date. | //| By default, the week starts on Sunday, unless superseded. | //| | //| StartOfWeek (D'2017.08.03 11:30') => 2017.07.30 00:00:00 | //+------------------------------------------------------------------+ datetime StartOfWeek(const datetime t, const bool StartsOnMonday = false) { int offset = (THURSDAY - StartsOnMonday) * DAYSECS; // 1 Jan 1970 is Thursday return t - ((t + offset) % WEEKSECS); } //+------------------------------------------------------------------+ //| Return the start of a month for the given date. | //+------------------------------------------------------------------+ datetime StartOfMonth(const datetime t) { MqlDateTime st; TimeToStruct(t, st); st.day = 1; st.hour = 0; st.min = 0; st.sec = 0; return StructToTime(st); } //+------------------------------------------------------------------+ //| Return the start of a year for the given date. | //+------------------------------------------------------------------+ datetime StartOfYear(const datetime t) { const int year = GetYear(t); MqlDateTime st = {year, 1, 1}; return StructToTime(st); } //+==================================================================+ //| 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. | //| By default, the week starts on Sunday, unless superseded. | //+------------------------------------------------------------------+ datetime EndOfWeek(const datetime t, const bool StartsOnMonday = false) { return StartOfWeek(t, StartsOnMonday) + (WEEKSECS - 1); } //+------------------------------------------------------------------+ //| Return the last second of a month for the given date. | //+------------------------------------------------------------------+ datetime EndOfMonth(const datetime t) { // MqlDateTime st; // TimeToStruct(t, st); // st.day = DaysInMonth(st.year, st.mon); // st.hour = 23; // st.min = 59; // st.sec = 59; // return(StructToTime(st)); MqlDateTime st; TimeToStruct(t, st); st.year += (st.mon == 12); st.mon = (st.mon % 12) + 1; st.day = 1; st.hour = 0; st.min = 0; st.sec = 0; return StructToTime(st) - 1; } //+------------------------------------------------------------------+ //| Return the last second of a year for the given date. | //+------------------------------------------------------------------+ datetime EndOfYear(const datetime t) { const int nextyear = GetYear(t) + 1; MqlDateTime st = {nextyear, 1, 1}; return StructToTime(st) - 1; } //+==================================================================+ //| SecsElapsedOf() Units | //+==================================================================+ //+------------------------------------------------------------------+ //| Seconds elapsed from the start of minute for the given date. | //+------------------------------------------------------------------+ int SecsElapsedOfMinute(const datetime t) { // return (int)(t - StartOfMinute(t)); return (int)(t % MINSECS); } //+------------------------------------------------------------------+ //| Seconds elapsed from the start of hour for the given date. | //+------------------------------------------------------------------+ int SecsElapsedOfHour(const datetime t) { // return (int)(t - StartOfHour(t)); return (int)(t % HOURSECS); } //+------------------------------------------------------------------+ //| Seconds elapsed from the start of day for the given date. | //+------------------------------------------------------------------+ int SecsElapsedOfDay(const datetime t) { // return (int)(t - StartOfDay(t)); return (int)(t % DAYSECS); } //+------------------------------------------------------------------+ //| Seconds elapsed from the start of week for the given date. | //| By default, the week starts on Sunday, unless superseded. | //+------------------------------------------------------------------+ int SecsElapsedOfWeek(const datetime t, const bool StartsOnMonday = false) { return (int)(t - StartOfWeek(t, StartsOnMonday)); } //+------------------------------------------------------------------+ //| 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 year for the given date. | //+------------------------------------------------------------------+ int SecsElapsedOfYear(const datetime t) { return (int)(t - StartOfYear(t)); } //+==================================================================+ //| 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. | //| By default, the week starts on Sunday, unless superseded. | //+------------------------------------------------------------------+ datetime RoundToWeek(const datetime t, const bool StartsOnMonday = false) { return StartOfWeek(t + WEEKSECS / 2, StartsOnMonday); } //+==================================================================+ //| 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. | //| By default, the week starts on Sunday, unless superseded. | //+------------------------------------------------------------------+ datetime CeilToWeek(const datetime t, const bool StartsOnMonday = false) { return StartOfWeek(t + WEEKSECS - 1, StartsOnMonday); } //+==================================================================+ //| Next() Weekday | //+==================================================================+ //+------------------------------------------------------------------+ //| Return the next day of the week after the given date. | //+------------------------------------------------------------------+ datetime NextWeekday(const datetime t, const ENUM_DAY_OF_WEEK weekday = SUNDAY) { int delta = weekday - DayOfWeek(t); if (delta <= 0) delta += 7; return StartOfDay(t + delta * DAYSECS); } //+------------------------------------------------------------------+ //| When is the next Sunday? | //+------------------------------------------------------------------+ datetime NextSunday(const datetime t) { return NextWeekday(t, SUNDAY); } //+------------------------------------------------------------------+ //| When is the next Monday? | //+------------------------------------------------------------------+ datetime NextMonday(const datetime t) { return NextWeekday(t, MONDAY); } //+------------------------------------------------------------------+ //| When is the next Tuesday? | //+------------------------------------------------------------------+ datetime NextTuesday(const datetime t) { return NextWeekday(t, TUESDAY); } //+------------------------------------------------------------------+ //| When is the next Wednesday? | //+------------------------------------------------------------------+ datetime NextWednesday(const datetime t) { return NextWeekday(t, WEDNESDAY); } //+------------------------------------------------------------------+ //| When is the next Thursday? | //+------------------------------------------------------------------+ datetime NextThursday(const datetime t) { return NextWeekday(t, THURSDAY); } //+------------------------------------------------------------------+ //| When is the next Friday? | //+------------------------------------------------------------------+ datetime NextFriday(const datetime t) { return NextWeekday(t, FRIDAY); } //+------------------------------------------------------------------+ //| When is the next Saturday? | //+------------------------------------------------------------------+ datetime NextSaturday(const datetime t) { return NextWeekday(t, SATURDAY); } //+==================================================================+ //| Previous() Weekday | //+==================================================================+ //+------------------------------------------------------------------+ //| Return the previous day of the week before the given date. | //+------------------------------------------------------------------+ datetime PreviousWeekday(const datetime t, const ENUM_DAY_OF_WEEK weekday = SUNDAY) { int delta = DayOfWeek(t) - weekday; if (delta <= 0) delta += 7; return StartOfDay(t - delta * DAYSECS); } //+------------------------------------------------------------------+ //| When is the previous Sunday? | //+------------------------------------------------------------------+ datetime PreviousSunday(const datetime t) { return PreviousWeekday(t, SUNDAY); } //+------------------------------------------------------------------+ //| When is the previous Monday? | //+------------------------------------------------------------------+ datetime PreviousMonday(const datetime t) { return PreviousWeekday(t, MONDAY); } //+------------------------------------------------------------------+ //| When is the previous Tuesday? | //+------------------------------------------------------------------+ datetime PreviousTuesday(const datetime t) { return PreviousWeekday(t, TUESDAY); } //+------------------------------------------------------------------+ //| When is the previous Wednesday? | //+------------------------------------------------------------------+ datetime PreviousWednesday(const datetime t) { return PreviousWeekday(t, WEDNESDAY); } //+------------------------------------------------------------------+ //| When is the previous Thursday? | //+------------------------------------------------------------------+ datetime PreviousThursday(const datetime t) { return PreviousWeekday(t, THURSDAY); } //+------------------------------------------------------------------+ //| When is the previous Friday? | //+------------------------------------------------------------------+ datetime PreviousFriday(const datetime t) { return PreviousWeekday(t, FRIDAY); } //+------------------------------------------------------------------+ //| When is the previous Saturday? | //+------------------------------------------------------------------+ datetime PreviousSaturday(const datetime t) { return PreviousWeekday(t, SATURDAY); } //+==================================================================+ //| Nth() Weekday Of The Month | //+==================================================================+ //+------------------------------------------------------------------+ //| Return the first day of the week of the month of the given date. | //+------------------------------------------------------------------+ datetime FirstWeekdayOfTheMonth(const datetime t, const ENUM_DAY_OF_WEEK weekday = SUNDAY) { return GetNthWeekdayInYearMonth(GetYear(t), GetMonth(t), 1, weekday); } //+------------------------------------------------------------------+ //| Return the last day of the week of the month of the given date. | //+------------------------------------------------------------------+ datetime LastWeekdayOfTheMonth(const datetime t, const ENUM_DAY_OF_WEEK weekday = SUNDAY) { return GetNthWeekdayInYearMonth(GetYear(t), GetMonth(t), 5, weekday); } //+------------------------------------------------------------------+ //| Return the "Nth" day of the week of the month of the given date. | //+------------------------------------------------------------------+ datetime NthWeekdayOfTheMonth(const datetime t, const int Nth, const ENUM_DAY_OF_WEEK weekday = SUNDAY) { return GetNthWeekdayInYearMonth(GetYear(t), GetMonth(t), Nth, weekday); } //+==================================================================+ //| 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 + (amount * MINSECS); } //+------------------------------------------------------------------+ //| Add the specified number of hours to the given date. | //+------------------------------------------------------------------+ datetime AddHours(const datetime t, const int amount) { return t + (amount * HOURSECS); } //+------------------------------------------------------------------+ //| Add the specified number of days to the given date. | //+------------------------------------------------------------------+ datetime AddDays(const datetime t, const int amount) { return t + (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) { datetime dt_result = t; int step = amount < 0 ? -1 : 1; int added = 0; while(added < MathAbs(amount)) { dt_result = AddDays(dt_result, step); int dow = DayOfWeek(dt_result); // Use modulo operator to check for weekends more efficiently if(dow % 6 != 0) { added++; } } return dt_result; } //+------------------------------------------------------------------+ //| Add the specified number of weeks to the given date. | //+------------------------------------------------------------------+ datetime AddWeeks(const datetime t, const int amount) { return t + (amount * WEEKSECS); } //+------------------------------------------------------------------+ //| Add the specified number of months to the given date. | //+------------------------------------------------------------------+ datetime AddMonths(const datetime t, const int amount) { MqlDateTime st; TimeToStruct(t, st); int totalMonths = st.year * 12 + (st.mon - 1) + amount; // month is 1-based st.year = totalMonths / 12; st.mon = (totalMonths % 12) + 1; st.day = MathMin(st.day, DaysInMonth(st.year, st.mon)); return StructToTime(st); } //+------------------------------------------------------------------+ //| Add the specified number of years to the given date. | //+------------------------------------------------------------------+ datetime AddYears(const datetime t, const int amount) { return AddMonths(t, amount * 12); } //+==================================================================+ //| 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 years from the given date. | //+------------------------------------------------------------------+ datetime SubYears(const datetime t, const int amount) { return AddYears(t, -amount); } //+==================================================================+ //| DifferenceIn() Units | //+==================================================================+ //+------------------------------------------------------------------+ //| Get the number of calendar days between the given dates. | //| the difference in days is calculated after removing times. | //+------------------------------------------------------------------+ int DifferenceInCalendarDays(const datetime beginTime, const datetime endTime) { return DayIndex(endTime) - DayIndex(beginTime); } //+------------------------------------------------------------------+ //| Get the number of business days (Mon - Fri) between the given | //| dates, excluding weekends. The end date is not included. | //+------------------------------------------------------------------+ int DifferenceInBusinessDays(const datetime beginTime, const datetime endTime) { datetime dt_temp = beginTime; int step = endTime < beginTime ? -1 : 1; int diff = 0; while(!IsSameDay(dt_temp, endTime)) { int dow = DayOfWeek(dt_temp); // Use modulo operator to check for weekends more efficiently if(dow % 6 != 0) { diff++; } dt_temp = AddDays(dt_temp, step); } return diff; } //+------------------------------------------------------------------+ //| Get the number of calendar weeks between the given dates. | //| the difference in weeks is calculated after removing days. | //| By default, the week starts on Sunday, unless superseded. | //+------------------------------------------------------------------+ int DifferenceInCalendarWeeks(const datetime beginTime, const datetime endTime, const bool StartsOnMonday = false) { return WeekIndex(endTime, StartsOnMonday) - WeekIndex(beginTime, StartsOnMonday); } //+------------------------------------------------------------------+ //| Get the number of calendar months between the given dates. | //| the difference in months is calculated after removing days. | //+------------------------------------------------------------------+ int DifferenceInCalendarMonths(const datetime beginTime, const datetime endTime) { const int yearsDiff = GetYear(endTime) - GetYear(beginTime); const int monthsDiff = GetMonth(endTime) - GetMonth(beginTime); return yearsDiff * 12 + monthsDiff; } //+==================================================================+ //| IsSame() Units | //+==================================================================+ //+------------------------------------------------------------------+ //| Are the given dates in the same minute (and hour and day)? | //+------------------------------------------------------------------+ bool IsSameMinute(const datetime t1, const datetime t2) { return StartOfMinute(t1) == StartOfMinute(t2); } //+------------------------------------------------------------------+ //| Are the given dates in the same hour (and same day)? | //+------------------------------------------------------------------+ bool IsSameHour(const datetime t1, const datetime t2) { return StartOfHour(t1) == StartOfHour(t2); } //+------------------------------------------------------------------+ //| Are the given dates in the same day (and year and month)? | //+------------------------------------------------------------------+ bool IsSameDay(const datetime t1, const datetime t2) { // return DayIndex(t1) == DayIndex(t2); return StartOfDay(t1) == StartOfDay(t2); } //+------------------------------------------------------------------+ //| Are the given dates in the same week (and month and year)? | //| By default, the week starts on Sunday, unless superseded. | //+------------------------------------------------------------------+ bool IsSameWeek(const datetime t1, const datetime t2, const bool StartsOnMonday = false) { return StartOfWeek(t1, StartsOnMonday) == StartOfWeek(t2, StartsOnMonday); } //+------------------------------------------------------------------+ //| Are the given dates in the same month (and year)? | //+------------------------------------------------------------------+ bool IsSameMonth(const datetime t1, const datetime t2) { return GetYear(t1) == GetYear(t2) && GetMonth(t1) == GetMonth(t2); } //+------------------------------------------------------------------+ //| Are the given dates in the same year? | //+------------------------------------------------------------------+ bool IsSameYear(const datetime t1, const datetime t2) { return GetYear(t1) == GetYear(t2); } //+==================================================================+ //| IsCurrent() Units | //+==================================================================+ //+------------------------------------------------------------------+ //| Is the given date in the same minute as the current server time | //+------------------------------------------------------------------+ bool IsCurrentMinute(const datetime t) { return IsSameMinute(t, TimeCurrent()); } //+------------------------------------------------------------------+ //| Is the given date in the same hour as the current server time | //+------------------------------------------------------------------+ bool IsCurrentHour(const datetime t) { return IsSameHour(t, TimeCurrent()); } //+------------------------------------------------------------------+ //| Is the given date in the same week as the current server time | //| By default, the week starts on Sunday, unless superseded. | //+------------------------------------------------------------------+ bool IsCurrentWeek(const datetime t, const bool StartsOnMonday = false) { return IsSameWeek(t, TimeCurrent(), StartsOnMonday); } //+------------------------------------------------------------------+ //| Is the given date in the same month as the current server time | //+------------------------------------------------------------------+ bool IsCurrentMonth(const datetime t) { return IsSameMonth(t, TimeCurrent()); } //+------------------------------------------------------------------+ //| Is the given date in the same year as the current server time | //+------------------------------------------------------------------+ bool IsCurrentYear(const datetime t) { return IsSameYear(t, TimeCurrent()); } //+------------------------------------------------------------------+ //| Is the given date today on the trade server | //+------------------------------------------------------------------+ bool IsToday(const datetime t) { return IsSameDay(t, TimeCurrent()); } //+------------------------------------------------------------------+ //| Is the given date tomorrow on the trade server | //+------------------------------------------------------------------+ bool IsTomorrow(const datetime t) { return IsSameDay(t, AddDays(TimeCurrent(), 1)); } //+------------------------------------------------------------------+ //| Is the given date yesterday on the trade server | //+------------------------------------------------------------------+ bool IsYesterday(const datetime t) { return IsSameDay(t, SubDays(TimeCurrent(), 1)); } //+==================================================================+ //| 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; } //+------------------------------------------------------------------+ //| Get the number of days in a month of the given year. | //+------------------------------------------------------------------+ 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)); } //+-------------------------------------------------------------------+ //| Return the date for the "Nth" weekday for the iYear and iMonth. | //| If "Nth" is larger than the number of Weekdays in the month, | //| return the last weekday. If "Nth" is otherwise invalid, return 0. | //+-------------------------------------------------------------------+ datetime GetNthWeekdayInYearMonth(int iYear, int iMonth, int Nth, ENUM_DAY_OF_WEEK weekday = SUNDAY) { MqlDateTime st = {iYear, iMonth, 1}; datetime dt = StructToTime(st); // get date of first of month datetime eom = dt + DaysInMonth(iYear, iMonth) * DAYSECS - 1; if(Nth < 1) return 0; if(Nth > 5) Nth = 5; dt = AddDays(dt, -1); dt = NextWeekday(dt, weekday); // move to 1st weekday of month dt = AddWeeks(dt, Nth - 1); dt = SubWeeks(dt, dt >= eom); // decrease one week if next month return dt; } //+------------------------------------------------------------------+ //| Return the date for the "Nth" Sunday for the iYear and iMonth. | //+------------------------------------------------------------------+ datetime GetNthSundayInYearMonth(int iYear, int iMonth, int Nth) { return GetNthWeekdayInYearMonth(iYear, iMonth, Nth, SUNDAY); } //+==================================================================+ //| Formating Time to String | //+==================================================================+ //+------------------------------------------------------------------+ //| Formats time with the weekday name => "Wed, 2023.02.14 01:59" | //+------------------------------------------------------------------+ string t2s(const datetime t, const int mode = TIME_DATE | TIME_MINUTES) { const string days[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; const int i = DayOfWeek(t); return days[i % 7] + ", " + 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); } //+------------------------------------------------------------------+ //| Returns 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 months[(uint)(monthNo - 1) % 12]; } //+------------------------------------------------------------------+ //| Returns 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 days[(uint)dayNo % 7]; } //+------------------------------------------------------------------+ //| 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" | //+------------------------------------------------------------------+ string TimeFormat(const datetime t, const string format = "YYYY.MM.DD hh:mm") { string retVal; MqlDateTime dt_struct; if(format == "" || StringLen(format) == 0) { Print("invalid format"); return ""; } if(TimeToStruct(t, dt_struct) == false) { Print("TimeToStruct() 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 MINSECS #undef HOURSECS #undef DAYSECS #undef WEEKSECS #undef YEARSECS #undef DAYSIN4YEARS #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( GetYear(t) ); Print( GetMonth(t) ); Print( GetDay(t) ); Print( GetHour(t) ); Print( GetMinute(t) ); Print( GetSecond(t) ); Print( DayOfWeek(t) ); Print( DayOfYear(t) ); MqlDateTime st[1] = {}; TimeToStructFast(t, st[0]); ArrayPrint(st); st[0].year += 1; Print(CreateDateTime(st[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 */ //+------------------------------------------------------------------+