Proper way to zero a datetime relative to the graph period

 
Hi,

I'm working on an indicator which grabs a mouse click and translate the X coordinate to a datetime value using ChartXYToTimePrice. The problem is that this function returns a "broken" datetime: while I'm in a M1 graph and I click in the candle at 12:00:00, the return value may come like 12:00:30 or 12:00:14 or 12:00:55. 

What I would like is to have the "clean" value of 12:00:00. The same, of course, working for other periods: if I'm in the M5 graph and click and get 12:04:23 or 12:06:23, I would like to actually get 12:05:00.

Now I'm aware I can work a solution of converting the datetime value to a MqlDateTime struct, do the changes, then go back to datetime, but that not only is ugly, but means lots of lines of workarounds. I would like to know if there is a more 'native' way of doing this; is there a way to make ChartXYToTimePrice already give the "candle-correct" datetime?
Documentation on MQL5: Constants, Enumerations and Structures / Data Structures / Date Type Structure
Documentation on MQL5: Constants, Enumerations and Structures / Data Structures / Date Type Structure
  • www.mql5.com
Constants, Enumerations and Structures / Data Structures / Date Type Structure - Reference on algorithmic/automated trading language for MetaTrader 5
 
datetime clean = broken - (broken % PeriodSeconds());
          Find bar of the same time one day ago - MQL4 programming forum
 
datetime roundedTime = (datetime) (realTime / PeriodSeconds());

should work too.
 
Soewono Effendi: datetime roundedTime = (datetime) (realTime / PeriodSeconds()); should work too.

No it will not: 4/5/2020 12:20:02 = 1586089202 → 1586089202 / 60 = 26,434,820 = 02 Nov 1970 23:00:20
          Online Conversion - Unix time conversion

Perhaps you forgot: datetime roundedTime = (datetime) (realTime / PeriodSeconds() * PeriodSeconds() );

 

Well thanks both William and Soewono! :)

Unfortunately, your answers ALMOST worked. Since they both truncate the seconds in datetime, what is happening is that when I click at the border of a candlestick, thus almost clicking the one before it, I already get a different value for the minute in datetime. So while I'm clicking in this candle, I end up getting the result that I clicked in the candle before it. So to truncate is not a perfect solution; I'm in need of a more perfect rounding :T

 
Martin Bittencourt:

Well thanks both William and Soewono! :)

Unfortunately, your answers ALMOST worked. Since they both truncate the seconds in datetime, what is happening is that when I click at the border of a candlestick, thus almost clicking the one before it, I already get a different value for the minute in datetime. So while I'm clicking in this candle, I end up getting the result that I clicked in the candle before it. So to truncate is not a perfect solution; I'm in need of a more perfect rounding :T

This will work:

         time = iTime(_Symbol,_Period,iBarShift(_Symbol,_Period,time+PeriodSeconds()/2));
 
Martin Bittencourt: I'm in need of a more perfect rounding :T

To round to the nearest integer, you add 1/2 and then truncate.

broken += PeriodSeconds() / 2;
datetime clean = broken - (broken % PeriodSeconds());
 
William Roeder:

To round to the nearest integer, you add 1/2 and then truncate.

Thanks both Seng and William! I tested William's solution, since it seems to require less computational power, and it worked perfectly :)

 
Martin Bittencourt:

Thanks both Seng and William! I tested William's solution, since it seems to require less computational power, and it worked perfectly :)

Unfortunately, I just realized that both our suggestions were flawed 🤪 - Try clicking on the first candle after a time gap (eg. Weekend) ... ... ... 
 
Seng Joo Thio: Unfortunately, I just realized that both our suggestions were flawed 🤪 - Try clicking on the first candle after a time gap (eg. Weekend) ... ... ... 

Wasn't thinking about that. Your solution (#5) works.

 
William Roeder:

Wasn't thinking about that. Your solution (#5) works.

No, my solution was equally flawed. There's a need to check for the time gap, so this will work (hope that @Martin Bittencourt will check back here... lol):

         rawtime += PeriodSeconds()/2;
         int bar = iBarShift(_Symbol,_Period,rawtime);
         datetime time = iTime(_Symbol,_Period,bar);
         if (rawtime>=time+PeriodSeconds())
            time = iTime(_Symbol,_Period,--bar);
Reason: