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