1449 lines
124 KiB
MQL5
1449 lines
124 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| 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
|
|
|
|
*/
|
|
//+------------------------------------------------------------------+
|