5

With MQL4 I have troubles in handling datetime.

What I want to do is put datetime in array by month or by year.

For now I do in this way.

datetime myDate;

myDate[0] = D'2010.01.01 00:00';
myDate[1] = D'2010.02.01 00:00';
myDate[2] = D'2010.03.01 00:00';
myDate[3] = D'2010.04.01 00:00';
.
.

However I want to do this like this below

myDate[0] = D'2010.01.01 00:00';
for (int i = 1;i < 6 ;i+=){
    myDate[i] = myDate[i - 1] + 1year;
}

in case of month,

myDate[0] = D'2010.01.01 00:00';
for (int i = 1; i < 12 ; i++){
    myDate[i] = myDate[i - 1] + 1month
}

Q: How do I calculate adding 1month or 1year?

user3666197
  • 1
  • 6
  • 50
  • 92
whitebear
  • 11,200
  • 24
  • 114
  • 237

6 Answers6

6

MQL4 documentation declared datetime type to be internally represented as an amount of seconds since an agreed time-scale datum ( being 1970-01-01 00:00 ).

This said ( and polishing a bit the syntax compliance )
the code
may read

oneYear = 60 * 60 * 24 * 365;   // yes, astronomers would kill me
                                // for not solving those seconds,
                                // that sum up until a leap year
                                // consumes 'em on Feb-29th day     :o)

another option
so as to manipulate
datetime in a bit more
comfortable manner, addressing
datetime's natural component is hacky, but worth: StringToTime

string TimeToString( datetime aDatetimeVALUE,
                     int aModeOfDISPLAY = TIME_DATE|TIME_MINUTES
                    )

Converting a value containing time in seconds elapsed since 01.01.1970 into a string of "yyyy.mm.dd hh:mi" format.

Here, one can simply add +1 to proper position of this intermediate format ( without a need to handle all the derived and influenced values as present in the struct MqlDateTime, where day_of_week and day_of_year are definitely not my favourite ones to re-calculate once moving +1 month etc.

aCurrentYEAR  = int(  StringSubstr( aDatetimeSTRING, 0, 4 ) );
aCurrentMONTH = int(  StringSubstr( aDatetimeSTRING, 5, 2 ) );
aCurrentDAY   = int(  StringSubstr( aDatetimeSTRING, 8, 2 ) );

aNextYEAR     = aCurrentYEAR  + 1;
aNextMONTH    = aCurrentMONTH + 1;

Finally

StringFormat( "%04d.%02d.%02d 00:00", aYearNUMBER, aMonthNUMBER, aDayNUMBER )

will do the re-assembly for calling another MQL4 standard function:

datetime StringToTime( string aDatetimeSTRING )

The function converts a string containing time or date in "yyyy.mm.dd [hh:mi]" format into datetime type.

Another approach may use a fully-decomposed datetime aritmetics by using

int aYE  = TimeYear(      aDatetimeVALUE );
int aMO  = TimeMonth(     aDatetimeVALUE );
int aDA  = TimeDay(       aDatetimeVALUE );
int aHO  = TimeHour(      aDatetimeVALUE );
int aMI  = TimeMinute(    aDatetimeVALUE );
int aDoW = TimeDayOfWeek( aDatetimeVALUE );
int aDoY = TimeDayOfYear( aDatetimeVALUE );

datetime aSameTimeNextYEAR = StructToTime( (MqlDateTime) { aYE + 1,
                                                           aMO,
                                                           aDA,
                                                           aHO,
                                                           aMI,
                                                           aDoW,
                                                           aDoY
                                                           }
                                           );
MohaMad
  • 2,575
  • 2
  • 14
  • 26
user3666197
  • 1
  • 6
  • 50
  • 92
  • Thanks I understood. There is a no simple way to add 1month, however this work-around is very helpful for me. – whitebear Nov 16 '16 at 06:00
4

Using MqlDateTime,TimeToStruct and StructToTimestructure like below:

MqlDateTime time;
TimeToStruct(TimeCurrent(),time);

time.year++;
time.mon++;
datetime newTime = StructToTime(time);
Hamid
  • 1,493
  • 2
  • 18
  • 32
0
int month = PeriodSeconds(PERIOD_MONTH);

for year - not sure that you can use some constant, but looks like 12 months is okay, another option is to use MqlDateTime assigning year and then converting to datetime using StructToTime();

UPDATE: month is not a good approach as every month has different number of seconds

Daniel Kniaz
  • 4,603
  • 2
  • 14
  • 20
  • 1
    Daniel, the `PERIOD_MONTH` is an artificial FOREX-flow of time "framing" serving a **constant** amount of seconds - definitely not the way to go for the asked problem, as a natural flow of time in February, with **`{28|29}`-calendar days** has by definition a different amount of seconds than in January, with **`31`-calendar days** – user3666197 Nov 12 '16 at 17:08
0

I attach a script illustrating the loop.

Essential logic:

  1. add 31 days to the defined datetime
  2. get the new month, ignoring the specific day
  3. generate the new date as a string with the new month
  4. convert the string into the new datetime
  5. add 31 days to this new datetime
  6. repeat from 2

    void OnStart(){

       datetime myDate[6];
       myDate[0] = D'2010.01.01 00:00';
       Print(TimeToStr(myDate[0]));

       datetime dTempDate = myDate[0];
       int iSecondsIn31Days = 24*60*60*31, iTempMonth = 0;

       for(int i=1; i<6; i++){
          iTempMonth = TimeMonth(dTempDate + iSecondsIn31Days); //add 31 days and get the month, we don't care whether the day is the 1st, 2nd, or 3rd, we just want the month
          myDate[i] = dTempDate = StrToTime(TimeYear(myDate[0]) +"." +iTempMonth +"." +TimeDay(myDate[0])); //format the string to datetime
          Print(TimeToStr(myDate[i])); //to verify
       }

    }

enter image description here

Michael Ng
  • 206
  • 2
  • 7
0

Methods you need to use

MqlDateTime , StructToTime ,TimeToStruct

You can do your job in less steps using these

Umit Terzi
  • 106
  • 1
  • 10
0

Old question, but I had the same issue.

As it is internally stored in seconds, just add the proper ammount of seconds. It is as easy as that....

   datetime date_from = TimeCurrent();
   // this adds two days from now (60*60 = 1 Hour) * (24 hours = 1 Day) * (2 = two days)
   date_from += 60*60*24*2;
   
   Comment(date_from);
shock_gone_wild
  • 6,700
  • 4
  • 28
  • 52