C++ datetime calculation api

本文介绍了一个使用C++中的localtime与mktime函数进行日期时间加减运算的示例,包括天数、月份数及年份的增减,并展示了如何打印格式化的日期时间。


Description


A sample of how use C++ localtime/mktime to implement datetime calculation, for example plus/minus a few days, months, years, etc.


Source Code:

#include <time.h>
#include <iomanip>

#include <iostream>

void printtm(const char * prefix, tm * tp) {
    std::cout << prefix;
    std::cout << std::setw(4) << std::setfill('0') << tp->tm_year + 1900;   // year
    std::cout << "/";
    std::cout << std::setw(2) << std::setfill('0') << tp->tm_mon + 1;   // month
    std::cout << "/";
    std::cout << std::setw(2) << std::setfill('0') << tp->tm_mday;  // day
    std::cout << " ";
    std::cout << std::setw(2) << std::setfill('0') << tp->tm_hour;  // hour
    std::cout << ":";
    std::cout << std::setw(2) << std::setfill('0') << tp->tm_min;   // minute
    std::cout << ":";
    std::cout << std::setw(2) << std::setfill('0') << tp->tm_sec;   // second
    std::cout << std::endl;
}

int main(int argc, char * argv[]) {
    time_t t = time(NULL);
    tm * tp = localtime(&t);
 
    printtm("today     :", tp);
    tp->tm_mday += 2; mktime(tp);
    printtm("+2 days   :", tp);  // 2 days later
    tp->tm_mon  += 2; mktime(tp);
    printtm("+2 months :", tp);  // 2 months later
    tp->tm_year -= 2; mktime(tp);
    printtm("-2 year   :", tp);  // 2 years before
    return 0;
}



Compile and execute:

$ g++ tt.cpp 
$ ./a.out 
today     :2015/12/29 04:16:25
+2 days   :2015/12/31 04:16:25
+2 months :2016/03/02 04:16:25
-2 year   :2014/03/02 04:16:25


Limitation:

Function localtime() is not thread-unsafe, it uses an internal memory space to keep the datetime data structure, when multiply calling localtime(..) they overwrite the same memory space.

So localtime() cannot be shared among multiply threads.



The end


#property link "https://www.earnforex.com/metatrader-indicators/volume-profile/" #property version "1.00" #property strict #property copyright "EarnForex.com - 2020-2021" #property description "The Volume Profile Indicator, also know as Market Profile" #property description "Shows you the price levels with most price action" #property description " " #property description "WARNING : You use this software at your own risk." #property description "The creator of these plugins cannot be held responsible for damage or loss." #property description " " #property description "Find More on EarnForex.com" #property indicator_chart_window #property indicator_buffers 3 enum ENUM_TRADE_SIGNAL{ SIGNAL_BUY=1, //BUY SIGNAL_SELL=-1, //SELL SIGNAL_NEUTRAL=0 //NEUTRAL }; enum ENUM_CALCULATION_START_TIME{ CALC_START_LAST=0, //MOST RECENT CANDLE CALC_START_MANUAL=1 //MANUAL SELECTION }; enum ENUM_CALCULATION_MODE{ CANDLE_WHOLE=0, //CANDLE WHOLE CANDLE_OPEN=2, //CANDLE OPEN CANDLE_CLOSE=3 //CANDLE CLOSE }; enum ENUM_CALCULATION_RANGE_TIMEFRAME{ CALC_TF_MINUTES=PERIOD_M1, //MINUTES CALC_TF_HOURS=PERIOD_H1, //HOURS CALC_TF_DAYS=PERIOD_D1, //DAYS CALC_TF_WEEKS=PERIOD_W1 //WEEKS }; enum ENUM_CANDLE_TO_CHECK{ CURRENT_CANDLE=0, //CURRENT CANDLE CLOSED_CANDLE=1 //PREVIOUS CANDLE }; enum ENUM_ALERT_SIGNAL{ }; input string Comment1="========================"; //MQLTA Volume Profile input string IndicatorName="MQLTA-VPI1"; //Indicator Short Name input string Comment2="========================"; //Indicator Parameters input ENUM_TIMEFRAMES VPTimeFrame=PERIOD_CURRENT; //Volume Profile Time Frame Calculation input ENUM_CALCULATION_MODE CalculationMode=CANDLE_WHOLE; //Value To Use For Calculation input bool UseVolume=true; //Use Volume In The Calculation input int StepPointsExt=10; //Step In Points input string Comment2a="========================"; //Time Range For Calculation input ENUM_CALCULATION_START_TIME StartTimeType=CALC_START_LAST; //Show Volume Profile Up To input int UnitsToScan=3; //Calculate With Previous (Number Of Units) input ENUM_CALCULATION_RANGE_TIMEFRAME UnitType=CALC_TF_DAYS; //Calculate With Previous (Type Of Units) input string Comment4="========================"; //Volume Profile Graph Parameters input int WindowSize=1; //Window Width Multiplier input color WindowColor=Blue; //Window Color input bool ShowLineLabel=true; //Show Vertical Line Label input color LineLabelColor=clrRed; //Vertical Line Label Color input bool CleanLineAtClose=true; //Delete Vertical Line At Close input string Comment5="========================"; //Point Of Control (POC) Parameters input bool ShowPOC=true; //Show POC Line input int POCSize=2; //POC Line Width (1 to 5) input color POCColor=clrRed; //POC Line Color long VolumeProfile[]; int Steps; int BarsToScan=0; int WindowSizeMin=10; int ChartScale; double StepPoints; double PriceMin; double PriceMax; datetime StartTime=TimeCurrent(); int OnInit(void){ IndicatorSetString(INDICATOR_SHORTNAME,IndicatorName); OnInitInitialization(); if(!OnInitPreChecksPass()){ return(INIT_FAILED); } InitialiseBuffers(); VolumeProfileCalculate(); return(INIT_SUCCEEDED); } int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]){ bool IsNewCandle=CheckIfNewCandle(); int pos,upTo; pos=0; if(prev_calculated==0 || IsNewCandle) upTo=BarsToScan-1; else upTo=0; if(IsNewCandle && StartTimeType==CALC_START_LAST){ StartTime=iTime(Symbol(),PERIOD_CURRENT,0); ObjectSetInteger(0,IndicatorName+"-VLINE-VP",OBJPROP_TIME,StartTime); VolumeProfileCalculate(); } return(rates_total); } void OnDeinit(const int reason){ CleanChart(); EventKillTimer(); } void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam){ if(id==CHARTEVENT_OBJECT_CLICK){ } if(id==CHARTEVENT_CHART_CHANGE){ ChartScale=(int)MathRound(ChartGetInteger(0,CHART_SCALE,0)); DrawVolumeProfile(); } if(id==CHARTEVENT_OBJECT_DRAG){ if(StringFind(sparam,IndicatorName+"-VLINE-VP",0)>=0){ StartTime=(datetime)ObjectGetInteger(0,IndicatorName+"-VLINE-VP",OBJPROP_TIME); VolumeProfileCalculate(); } } } void OnTimer(){ StartTime=(datetime)ObjectGetInteger(0,IndicatorName+"-VLINE-VP",OBJPROP_TIME); VolumeProfileCalculate(); } void OnInitInitialization(){ StepPoints=StepPointsExt*Point(); ChartScale=(int)MathRound(ChartGetInteger(0,CHART_SCALE,0)); BarsToScan=PeriodSeconds((ENUM_TIMEFRAMES)UnitType)*UnitsToScan/PeriodSeconds(VPTimeFrame); ScanLines(); CreateLine(); StartTime=(datetime)ObjectGetInteger(0,IndicatorName+"-VLINE-VP",OBJPROP_TIME); if(StartTimeType==CALC_START_LAST){ EventSetTimer(10); } } bool OnInitPreChecksPass(){ if(iBars(Symbol(),VPTimeFrame)<BarsToScan){ Alert("Insufficient Historical Data, only ",iBars(Symbol(),VPTimeFrame)," found in the time frame requested"); printf("Insufficient Historical Data, only ",iBars(Symbol(),VPTimeFrame)," found in the time frame requested"); return false; } return true; } void CleanChart(){ int Window=0; for(int i=ObjectsTotal(ChartID(),Window,-1)-1;i>=0;i--){ if(StringFind(ObjectName(0,i),IndicatorName,0)>=0 && (StringFind(ObjectName(0,i),"-VLINE-VP",0)<0 || CleanLineAtClose || StartTimeType==CALC_START_LAST)){ ObjectDelete(0,ObjectName(0,i)); } } } void InitialiseBuffers(){ IndicatorBuffers(3); IndicatorDigits(Digits); } datetime NewCandleTime=TimeCurrent(); bool CheckIfNewCandle(){ if(NewCandleTime==iTime(Symbol(),0,0)) return false; else{ NewCandleTime=iTime(Symbol(),0,0); return true; } } void VolumeProfileCalculate(){ int BarStart=iBarShift(Symbol(),VPTimeFrame,StartTime); int PriceHighMode=MODE_CLOSE; int PriceLowMode=MODE_CLOSE; if(CalculationMode==CANDLE_WHOLE){ PriceHighMode=MODE_HIGH; PriceLowMode=MODE_LOW; } if(CalculationMode==CANDLE_CLOSE){ PriceHighMode=MODE_CLOSE; PriceLowMode=MODE_CLOSE; } if(CalculationMode==CANDLE_OPEN){ PriceHighMode=MODE_OPEN; PriceLowMode=MODE_OPEN; } PriceMin=MathFloor(iLow(Symbol(),VPTimeFrame,iLowest(Symbol(),VPTimeFrame,PriceLowMode,BarsToScan,BarStart))/StepPoints)*StepPoints; PriceMax=MathCeil(iHigh(Symbol(),VPTimeFrame,iHighest(Symbol(),VPTimeFrame,PriceHighMode,BarsToScan,BarStart))/StepPoints)*StepPoints; Steps=(int)MathCeil((PriceMax-PriceMin)/StepPoints)+1; ArrayResize(VolumeProfile,Steps); ArrayInitialize(VolumeProfile,0); for(int i=0; i<BarsToScan; i++){ int j=BarStart+i; double MinPrice=0; double MaxPrice=0; double CandleSteps=0; if(CalculationMode==CANDLE_WHOLE){ MinPrice=iLow(Symbol(),VPTimeFrame,j); MaxPrice=iHigh(Symbol(),VPTimeFrame,j); } if(CalculationMode==CANDLE_CLOSE){ MinPrice=iClose(Symbol(),VPTimeFrame,j); MaxPrice=iClose(Symbol(),VPTimeFrame,j); } if(CalculationMode==CANDLE_OPEN){ MinPrice=iOpen(Symbol(),VPTimeFrame,j); MaxPrice=iOpen(Symbol(),VPTimeFrame,j); } MinPrice=MathFloor(MinPrice/StepPoints)*StepPoints; MaxPrice=MathFloor(MaxPrice/StepPoints)*StepPoints; CandleSteps=MathRound((MaxPrice-MinPrice)/StepPoints); for(int k=0; k<=CandleSteps; k++){ double CalcPrice=MinPrice+StepPoints*k; int h=(int)MathRound((CalcPrice-PriceMin)/StepPoints); long Weight=1; if(UseVolume) Weight=iVolume(Symbol(),VPTimeFrame,j); //Print(Steps," - ",i," - ",k," - ",MinPrice," - ",MaxPrice," - ",PriceMin," - ",PriceMax," - ",CalcPrice," - ",CandleSteps," - ",h); VolumeProfile[h]+=Weight; } } DrawVolumeProfile(); } void DrawVolumeProfile(){ CleanVolumeProfile(); long VolumeMax=VolumeProfile[ArrayMaximum(VolumeProfile)]; long VolumeMin=VolumeProfile[ArrayMinimum(VolumeProfile)]; long VolumeDiffMax=VolumeMax-VolumeMin; double PricePOC=PriceMin+StepPoints*ArrayMaximum(VolumeProfile)+StepPoints/2; int VolumeWidth=(int)MathRound(WindowSizeMin*WindowSize*(6-ChartGetInteger(0,CHART_SCALE))); for(int i=0; i<ArraySize(VolumeProfile); i++){ double PriceLow=PriceMin+StepPoints*i; double PriceHigh=PriceLow+StepPoints; datetime TimeRight=StartTime; int StartTimeShift=iBarShift(Symbol(),PERIOD_CURRENT,StartTime); long VolumeDiff=VolumeProfile[i]-VolumeMin; //int TimeStepsShift=(int)MathRound((VolumeWidth*VolumeDiff)/VolumeDiffMax); int TimeStepsShift=(int)MathRound(((VolumeWidth-1)*VolumeProfile[i])/VolumeMax); //Print(VolumeMax," - ",VolumeMin," - ",VolumeProfile[i]," - ",VolumeMin," - ",VolumeDiff," - ",TimeStepsShift); datetime TimeLeft=iTime(Symbol(),PERIOD_CURRENT,StartTimeShift+TimeStepsShift+1); string RectangleName=IndicatorName+"-VP-RECT-"+DoubleToString(PriceLow/Point(),0); ObjectCreate(0,RectangleName,OBJ_RECTANGLE,0,TimeRight,PriceLow,TimeLeft,PriceHigh); ObjectSetInteger(0,RectangleName,OBJPROP_COLOR,WindowColor); ObjectSetInteger(0,RectangleName,OBJPROP_SELECTABLE,false); ObjectSetInteger(0,RectangleName,OBJPROP_BACK,true); ObjectSetInteger(0,RectangleName,OBJPROP_HIDDEN,true); } if(ShowPOC){ string POCName=IndicatorName+"-VP-RECT-H-"+DoubleToString(PricePOC/Point(),0); ObjectCreate(0,POCName,OBJ_HLINE,0,0,PricePOC); ObjectSetInteger(0,POCName,OBJPROP_COLOR,POCColor); ObjectSetInteger(0,POCName,OBJPROP_WIDTH,POCSize); ObjectSetInteger(0,POCName,OBJPROP_SELECTABLE,false); } UpdateLineLabels(); } void CleanVolumeProfile(){ int Window=0; for(int i=ObjectsTotal(ChartID(),Window,-1)-1;i>=0;i--){ if(StringFind(ObjectName(0,i),IndicatorName+"-VP-RECT-",0)>=0 || StringFind(ObjectName(0,i),IndicatorName+"-VLINE-LABEL",0)>=0){ ObjectDelete(0,ObjectName(0,i)); } } } int TotalLines=0; void ScanLines(){ TotalLines=0; for(int i=0;i<ObjectsTotal();i++){ if(StringFind(ObjectName(0,i),IndicatorName+"-VLINE-VP",0)>=0){ TotalLines++; StartTime=(datetime)ObjectGetInteger(0,IndicatorName+"-VLINE-VP",OBJPROP_TIME); break; } } } void CreateLine(){ string LineName=IndicatorName+"-VLINE-VP"; if(TotalLines==0){ ObjectCreate(0,LineName,OBJ_VLINE,0,iTime(Symbol(),PERIOD_CURRENT,0),0); } ObjectSetInteger(0,LineName,OBJPROP_COLOR,WindowColor); ObjectSetInteger(0,LineName,OBJPROP_BACK,true); if(StartTimeType==CALC_START_LAST){ ObjectSetInteger(0,LineName,OBJPROP_SELECTABLE,false); ObjectSetInteger(0,LineName,OBJPROP_TIME,iTime(Symbol(),PERIOD_CURRENT,0)); } else{ ObjectSetInteger(0,LineName,OBJPROP_SELECTABLE,true); } ObjectSetInteger(0,LineName,OBJPROP_WIDTH,1); UpdateLineLabels(); } void UpdateLineLabels(){ if(!ShowLineLabel) return; string LabelName=IndicatorName+"-VLINE-LABEL"; ObjectCreate(0,LabelName,OBJ_TEXT,0,0,0); ObjectSetDouble(0,LabelName,OBJPROP_ANGLE,90); ObjectSetInteger(0,LabelName,OBJPROP_ANCHOR,ANCHOR_LEFT_UPPER); ObjectSetInteger(0,LabelName,OBJPROP_COLOR,WindowColor); int Y=(int)MathRound(ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS,0)-10); double PriceY=0; int SubW=0; string UnitString=""; if(UnitType==CALC_TF_DAYS) UnitString="DAYS"; if(UnitType==CALC_TF_HOURS) UnitString="HOURS"; if(UnitType==CALC_TF_MINUTES) UnitString="MINUTES"; if(UnitType==CALC_TF_WEEKS) UnitString="WEEKS"; string LabelDescr=IndicatorName+"-VP- PREVIOUS "+IntegerToString(UnitsToScan)+" "+UnitString; datetime TimeTmp=TimeCurrent(); ChartXYToTimePrice(0,0,Y,SubW,TimeTmp,PriceY); ObjectSetInteger(0,LabelName,OBJPROP_TIME,StartTime); ObjectSetDouble(0,LabelName,OBJPROP_PRICE,PriceY); ObjectSetInteger(0,LabelName,OBJPROP_HIDDEN,false); ObjectSetText(LabelName,LabelDescr,10,"Consolas",LineLabelColor); } void DeleteAllLines(){ int Window=0; for(int i=ObjectsTotal(ChartID(),Window,-1)-1;i>=0;i--){ if(StringFind(ObjectName(i),IndicatorName,0)>=0 && StringFind(ObjectName(i),IndicatorName+"-VLINE-",0)>=0){ ObjectDelete(ObjectName(i)); } } }转通达信,博易指标代码
最新发布
10-07
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值