//+------------------------------------------------------------------+
//|                                                    P4L Clock.mq4 |
//| New rewrite by: Pips4life, a user at forexfactory.com            |
//| 2008-09-28: v2_3  P4L Clock.mq4                                  |
//|  (See Version History below)                                     |
//|                                                                  |
//| Previous names: Clock_v1_3.mq4, Clock.mq4, ...                   |
//| Previous version:   Jerome,  4xCoder@gmail.com, ...              |
//|                                                                  |
//+------------------------------------------------------------------+
//
// Version History:
// 2008-09-28: v2_3  pips4life:
//    Added Auckland, Moscow, Berlin, Seattle for Jodie(jhp2025). Default topOffsetPixels is now 10.
// 2008-09-28: v2_2  pips4life: Turns out the ST/DST crossover dates are good
//    until any market zone country legistlatively changes their dates.
//    No annual update is necessary!  I updated the comments accordingly.
//    I moved the init() block before start for easier readability of the flow.
//    Mostly cosmetic changes.
// 2008-09-27: v2_1  pips4life: 
//    Modified Sydney changes NuckingFuts made. (Thx for the prelim work).
//    The original world time ST/DST calculation method which I had not looked
//    at enough to understand is fatally flawed, so...all that is rewritten! 
//    The new method uses true clock data and  *should* work from every timezone, 
//    and *should* handle ST/DST changes for each TZ, independently,
//    regardless of your local TS and/or ST/DST status. (Depends on Windows
//    being correct, however). CONSEQUENTLY, the changes require ANNUAL UPDATES
//    to get the world ST/DST changeover dates!! Check this thread for updates:
//       http://forexfactory.com/showthread.php?t=109305
//    If no update, in JUST ONE CHART (!!), set If_TZ_ChangesSetTrueOn_ONE_chart=TRUE 
//    and follow the directions...  Do NOT compile the code with that variable=TRUE!!
//    Added Weekend_Test_Mode so simulated ticks show true times over the weekend.
// 2008-09-25:  mods by NuckingFuts
//    Fixed timezones with no daylight savings
//    Added Sydney
// 2008-09-24:  v2_0 "P4L Clock.mq4" by pips4life @ forexfactory.com 
//    Different highlight color(s) used for Market Open hours (Assuming 8AM - 5PM local market hours)
//    Added seconds display, and used method such that single digits look better (":09" not ":9")
//    Added "Broker_MMSS_Is_Gold_Standard" to adjust (by a few seconds or minutes) the market hours, because
//      as if often the case, the local computer clock may be off by a small amount.
//    Two extern variables to control display of seconds: bool Display_Time_With_Seconds, int Display_Bar_With_Seconds.
//    When Display_Bar_With_Seconds=2 (Auto mode), seconds display when < 2min, OR, if Display_Time_With_Seconds=True.
//    "Bar:" changed to "Bar Left:" (remaining time). Also, it will say "wait4bar" (rather than to display
//      a negative number as would have occurred) during periods of low activity until a new bar is formed.
//    "Suppress_Bar_HH_Below_H1" displays only [MM:SS] for H1 and below since HH in [HH:MM:SS] is always "00" 
//    Adjusted pixel distance between labels depending on options.
//    "Bar Left:" time does not display above D1 charts.  A future enhancement (not planned) could report DD_HH:MM[:SS]
//    Added Show_DIBS_London clock with user-setable start/stop hour relative to London (6AM and 7PM at present).
//
// 2008-??   v1_4  Was NOT an indicator, rather a script; however, it didn't handle new bars (Time[0] stuck), nor could
//    one change timeframes without having to "Disable" and re-add the script. May have been more CPU intensive??
// 2008-??   v1_3 and earlier.  Details can be found on the web.

//#property copyright "Jerome" //previous author
//#property link      "4xCoder@gmail.com"
#property copyright "pips4life" //P4L Clock.mq4 is rewrite of Clock.mq4, Clock_v1_3.mq4
#property link      "pips4life, a user at forexfactory.com"

#import "kernel32.dll"
void GetLocalTime(int& localTimeArray[]);
void GetSystemTime(int& systemTimeArray[]);
int  GetTimeZoneInformation(int& localTZInfoArray[]);
bool SystemTimeToTzSpecificLocalTime(int& targetTZinfoArray[], int& systemTimeArray[], int& targetTimeArray[]);
#import

//------------------------------------------------------------------
// Instructions
//    Copy this file to:  C:\Program Files\--your-MT4-directory-here---\experts\indicators
//    Review the "extern" variable settings below. Change as desired, then restart MT4 or do "Compile" in MetaEditor.
//    
//    Open a chart and add this indicator. Assuming you compiled with the "extern" defaults you prefer,
//    you shouldn't need to change any of the defaults, *except* one:
//    ***This Version requires "Allow DLL Imports" be set in Common Tab when you add this to a chart!
//    FYI, the DLLs retrieve the local CPU clock time and timezone info as well as world timezone info.
//
//    NOTE! The world timezone times are only as accurate as your LOCAL CPU CLOCK! Verify and set it accurately!
//    NOTE! Your Broker time is independent.
// DISCLAIMER: Use completely at your own risk!! Author(s) accept no liabilities whatsoever!

#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 Red


//---- input parameters -- FYI, THE USER MAY CUSTOMIZE THESE EXTERN VARIABLE SETTINGS AS DESIRED:
extern string   _INFO_Set_your_computer_clock = "Accuracy depends on YOUR CPU CLOCK!!";
extern string   _INFO_Verify_times_with_URL   = "http://www.worldtimezone.net/index24.php";
extern string   _INFO_Re_labelCorner          = "0=Top-left, 1=TR, 2=BL, 3=BR";
extern int      labelWindow                   = 1;
extern int      labelCorner                   = 1;          // 1 & 3 work best:  0=top-left; 1=top-right; 2=bottom-left; 3=bottom-right
extern int      topOffsetPixels               = 2;         // 10 pixels from top to show the 1st clock ("Bar Left:")
extern int      leftLabelOffset               = 50;
extern int      rightLabelOffset              = 6;
extern color    labelColor                    = DarkGreen;  // Color of label, off-hours
extern color    clockColor                    = MediumBlue; // Color of clock, off-hours
extern color    labelMktOpenColor             = Red;        // Color of label, market-open
extern color    clockMktOpenColor             = Red;        // Color of clock, market-open
extern bool     Highlight_Market_Open         = true ;      // When true, the above market-open colors are used between 8AM - 5PM (market local)
extern bool     Display_Times_With_AMPM       = false;      // True=show 12 hour AM/PM time, false=show 24 hour time
extern bool     Broker_MMSS_Is_Gold_Standard  = true ;      // If true, make a correction up to a few seconds/minutes vs. your local CPU clock. FYI, we don't know Broker TZ/DST info but don't care.
extern bool 	 Display_Time_With_Seconds     = false;      // Turn on seconds.
extern string   _INFO_Re_Bar_With_Seconds      = "0=No; 1=Yes; 2=Auto"; // Auto is: if < 120 seconds or if Display_Time_With_Seconds is true.
extern int  	 Display_Bar_With_Seconds      = 1;          // Control "Bar Left:" to display ":SS" independently from other times.
extern bool     ShowAuckland                  = true ;
extern bool     ShowSydney                    = true ;
extern bool     ShowTokyo                     = true ;
extern bool     ShowMoscow                    = true ;
extern bool     ShowBerlin                    = true ;
extern bool 	 ShowLondon                    = true ;
extern bool 	 ShowNewYork                   = true ;
extern bool 	 ShowSeattle                   = true ;
extern bool 	 ShowUTC_GMT                   = true ; // FYI, UTC_GMT does not change with Daylight Savings Time. In winter, London=UTC; in summer, London=UTC+1
extern bool     ShowLocal                     = true ; // FYI, this is your local computer clock.  Your clock should be accurate for all other timezones to be accurate!!
extern bool     Show_DIBS_London              = false; // FYI, for DIBS method, see http://www.forexfactory.com/showthread.php?t=86766
extern int      DIBS_LondonOpenHour           = 6;     // DIBS relative to London local time. 6 ~= 2 hours before London ~= Chicago midnight. (Follows London DST)
extern int      DIBS_LondonCloseHour          = 15;    // MAX is 23!! Subjective choice. Change as desired. 9 hours length?? (Do NOT use # < DIBS_LondonOpenHour). 
extern bool     Weekend_Test_Mode             = false; // Normally false. True forces Broker_MMSS_Is_Gold_Standard=false as well. Clock updates are >=once-per-broker-second but on weekends the Broker clock freezes
//

// FYI: If a market zone changes ST/DST dates (e.g. if Tokyo adopts DST), or, to add a new market timezone to this program,
//   you need to obtain the timezone ST/DST crossover date information.  To do that, add "extern" before this variable but leave it FALSE!
//  Add indicator to one chart and set this variable True ON ONE CHART ONLY, then follow the directions...
// WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!
//extern
bool  New_DST_SetTrueOnONEchart   = FALSE; // WARNING! Do NOT compile this as TRUE! Rather, make it "extern bool", compile, then change just ONE CHART value to TRUE for instructions!

//---- buffers

int    localTZInfoArray[43];
int    newyorkTZInfoArray[43];
int    londonTZInfoArray[43];
int    tokyoTZInfoArray[43];
int    sydneyTZInfoArray[43];
int    aucklandTZInfoArray[43];
int    moscowTZInfoArray[43];
int    berlinTZInfoArray[43];
int    seattleTZInfoArray[43];


double ExtMapBuffer1[];
//int LondonTZ = 0; // These offsets aren't needed any more
//int TokyoTZ = 9;
//int SydneyTZ = 10;
//int NewYorkTZ = -5;


// Most local markets assumed open 8AM to 5PM
int localOpenHour = 8;
int localCloseHour = 17;

// Sydney market local is 7am-4pm per "NuckingFuts"
int sydneyLocalOpenHour = 7;
int sydneyLocalCloseHour = 16;


//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
   SetIndexStyle(0,DRAW_LINE);
   SetIndexBuffer(0,ExtMapBuffer1);
   
   if (New_DST_SetTrueOnONEchart) writeLocalTZInfoToFile("tzdata.csv", false); // The false obtains only the limited data which is needed.
   
   GetAllTimeZoneInfo(localTZInfoArray, newyorkTZInfoArray, londonTZInfoArray, tokyoTZInfoArray, sydneyTZInfoArray, aucklandTZInfoArray, moscowTZInfoArray, berlinTZInfoArray, seattleTZInfoArray);
   
   int top=topOffsetPixels;
   int left = leftLabelOffset;
   int right = rightLabelOffset;
   if (!Display_Times_With_AMPM && !Display_Time_With_Seconds && Display_Bar_With_Seconds == 0) right = rightLabelOffset;
   else if (Display_Times_With_AMPM && !Display_Time_With_Seconds) right = rightLabelOffset;
   
   if ( Display_Times_With_AMPM )
      left = leftLabelOffset;
   int offset=0;

   // BrokerTime always displays
   ObjectMakeLabel( "brol", left, top+offset );
   ObjectMakeLabel( "brot", right, top+offset );
  	offset+=15;
  	//
   if(ShowAuckland)
   {
   	ObjectMakeLabel( "auckl", left, top+offset );
   	ObjectMakeLabel( "auckt", right, top+offset );
   	offset+=15;
   }
   if(ShowSydney)
   {
   	ObjectMakeLabel( "sydl", left, top+offset );
   	ObjectMakeLabel( "sydt", right, top+offset );
   	offset+=15;
   }
   if(ShowTokyo)
   {
   	ObjectMakeLabel( "tokl", left, top+offset );
   	ObjectMakeLabel( "tokt", right, top+offset );
   	offset+=15;
   }
   if(ShowMoscow)
   {
   	ObjectMakeLabel( "mosl", left, top+offset );
   	ObjectMakeLabel( "most", right, top+offset );
   	offset+=15;
   }
   if(ShowBerlin)
   {
   	ObjectMakeLabel( "berl", left, top+offset );
   	ObjectMakeLabel( "bert", right, top+offset );
   	offset+=15;
   }
   if(ShowLondon)
   {
	   ObjectMakeLabel( "lonl", left, top+offset );
   	ObjectMakeLabel( "lont", right, top+offset );
   	offset+=15;
   }
   if(ShowNewYork)
   {
	   ObjectMakeLabel( "nyl", left, top+offset );
   	ObjectMakeLabel( "nyt", right, top+offset );
   	offset+=15;
   }
   if(ShowSeattle)
   {
	   ObjectMakeLabel( "seal", left, top+offset );
   	ObjectMakeLabel( "seat", right, top+offset );
   	offset+=15;
   }
   if(ShowUTC_GMT)
   {
   	ObjectMakeLabel( "utcl", left, top+offset );
   	ObjectMakeLabel( "utct", right, top+offset );
   	offset+=15;
   }
   if ( Show_DIBS_London ) {
      ObjectMakeLabel( "dibsl", left, top+offset );
      ObjectMakeLabel( "dibst", right, top+offset );
      offset+=15;
   }
   if ( ShowLocal ) {
      ObjectMakeLabel( "locl", left, top+offset );
      ObjectMakeLabel( "loct", right, top+offset );
      offset+=15;
   }

//----
   return(0);
  } // end of init()
//+------------------------------------------------------------------+
//| Custom indicator iteration function -- Runs with each new tick   |
//+------------------------------------------------------------------+
int start()
  {
   static datetime last_timecurrent;
   if ( !IsDllsAllowed() ) 
   {
      if (TimeCurrent() - last_timecurrent < 7) return; // With a lot of fast ticks, this error message would be annoying if not delayed a bit
      last_timecurrent = TimeCurrent();
      Alert( WindowExpertName(),": ERROR. DLLs are disabled. To enable, select 'Allow DLL Imports' in the Common Tab of indicator" );
      return;
   }
   
   // FYI, if uncommented, saves CPU but won't update on weekends. If commented, on weekends the Broker_MMSS_Is_Gold_Standard must be FALSE. Better, just use Weekend_Test_Mode=true to update every tick.
   if (!Weekend_Test_Mode && TimeCurrent() - last_timecurrent == 0) return; // No point in processing more than 1 tick per second.
   last_timecurrent = TimeCurrent();
   
   int    localTimeArray[4];
   int    systemTimeArray[4];
   int    newyorkTimeArray[4];
   int    londonTimeArray[4];
   int    tokyoTimeArray[4];
   int    sydneyTimeArray[4];
   int    aucklandTimeArray[4];
   int    moscowTimeArray[4];
   int    berlinTimeArray[4];
   int    seattleTimeArray[4];
   
   
   GetLocalTime(localTimeArray);
   datetime localTime = TimeArrayToTime(localTimeArray);

   datetime brokerTime = TimeCurrent();
   datetime brokerCorrection = 0;
   
   if (Broker_MMSS_Is_Gold_Standard && !Weekend_Test_Mode) 
   {
      brokerCorrection = TimeMinute(brokerTime)*60 + TimeSeconds(brokerTime) - TimeMinute(localTime)*60 - TimeSeconds(localTime);
      if (brokerCorrection > 1800) brokerCorrection = brokerCorrection - 3600;
      else if (brokerCorrection < -1800) brokerCorrection = brokerCorrection + 3600;
      //Alert("brokerCorrection seconds: ", brokerCorrection);
   }   
     
   GetSystemTime(systemTimeArray);
   datetime UTC = TimeArrayToTime(systemTimeArray)+brokerCorrection;

   SystemTimeToTzSpecificLocalTime(newyorkTZInfoArray, systemTimeArray, newyorkTimeArray);
   datetime newyork = TimeArrayToTime(newyorkTimeArray)+brokerCorrection;
   
   SystemTimeToTzSpecificLocalTime(sydneyTZInfoArray, systemTimeArray, sydneyTimeArray);
   datetime sydney  = TimeArrayToTime(sydneyTimeArray)+brokerCorrection;
   
   SystemTimeToTzSpecificLocalTime(londonTZInfoArray, systemTimeArray, londonTimeArray);
   datetime london  = TimeArrayToTime(londonTimeArray)+brokerCorrection;
   
   SystemTimeToTzSpecificLocalTime(tokyoTZInfoArray, systemTimeArray, tokyoTimeArray);
   datetime tokyo   = TimeArrayToTime(tokyoTimeArray)+brokerCorrection;
      
   SystemTimeToTzSpecificLocalTime(aucklandTZInfoArray, systemTimeArray, aucklandTimeArray);
   datetime auckland   = TimeArrayToTime(aucklandTimeArray)+brokerCorrection;
      
   SystemTimeToTzSpecificLocalTime(moscowTZInfoArray, systemTimeArray, moscowTimeArray);
   datetime moscow   = TimeArrayToTime(moscowTimeArray)+brokerCorrection;
      
   SystemTimeToTzSpecificLocalTime(berlinTZInfoArray, systemTimeArray, berlinTimeArray);
   datetime berlin   = TimeArrayToTime(berlinTimeArray)+brokerCorrection;
      
   SystemTimeToTzSpecificLocalTime(seattleTZInfoArray, systemTimeArray, seattleTimeArray);
   datetime seattle   = TimeArrayToTime(seattleTimeArray)+brokerCorrection;
      
   string UTCs = TimeToString( UTC );
   string sydneys = TimeToString(sydney);
   string locals = TimeToString( localTime  );
   string londons = TimeToString( london  );
   string tokyos = TimeToString( tokyo  );
   string aucklands = TimeToString( auckland  );
   string moscows = TimeToString( moscow  );
   string berlins = TimeToString( berlin  );
   string seattles = TimeToString( seattle  );
   string newyorks = TimeToString( newyork  );
   string brokers = TimeToString( TimeCurrent() );

   if(Show_DIBS_London)
   {
   	if (TimeDayOfWeek(london) != 0 && TimeDayOfWeek(london) != 6 && Highlight_Market_Open && TimeHour(london) >= DIBS_LondonOpenHour && TimeHour(london) < DIBS_LondonCloseHour)
   	{
   	   ObjectSetText( "dibsl", "* DIBS UK:", 10, "Arial", labelMktOpenColor );
      	ObjectSetText( "dibst", londons, 10, "Arial",clockMktOpenColor );
   	}
   	else
   	{
   	   ObjectSetText( "dibsl", "DIBS UK:", 10, "Arial", labelColor );
      	ObjectSetText( "dibst", londons, 10, "Arial",clockColor );
      }
   }
   if ( ShowLocal ) {
      ObjectSetText( "locl", "Local:", 10, "Arial", labelColor );
      ObjectSetText( "loct", locals, 10, "Arial",clockColor );
   }
   if(ShowUTC_GMT)
   {
   	ObjectSetText( "utcl", "UTC_GMT:", 10, "Arial", labelColor );
   	ObjectSetText( "utct", UTCs, 10, "Arial",clockColor );
   }
   if(ShowNewYork)
   {
   	if (TimeDayOfWeek(newyork) != 0 && TimeDayOfWeek(newyork) != 6 && Highlight_Market_Open && TimeHour(newyork) >= localOpenHour && TimeHour(newyork) < localCloseHour)
   	{
   	   ObjectSetText( "nyl", "* New York:", 10, "Arial", labelMktOpenColor );
      	ObjectSetText( "nyt", newyorks, 10, "Arial",clockMktOpenColor );
   	}
   	else
   	{
   	   ObjectSetText( "nyl", "New York:", 10, "Arial", labelColor );
      	ObjectSetText( "nyt", newyorks, 10, "Arial",clockColor );
      }
   }
   if(ShowLondon)
   {
   	if (TimeDayOfWeek(london) != 0 && TimeDayOfWeek(london) != 6 && Highlight_Market_Open && TimeHour(london) >= localOpenHour && TimeHour(london) < localCloseHour)
   	{
      	ObjectSetText( "lonl", "* London:", 10, "Arial", labelMktOpenColor );
      	ObjectSetText( "lont", londons, 10, "Arial",clockMktOpenColor );
   	}
   	else
   	{
   	   ObjectSetText( "lonl", "London:", 10, "Arial", labelColor );
   	   ObjectSetText( "lont", londons, 10, "Arial",clockColor );
   	}
   }
   if(ShowTokyo)
   {
   	if (TimeDayOfWeek(tokyo) != 0 && TimeDayOfWeek(tokyo) != 6 && Highlight_Market_Open && TimeHour(tokyo) >= localOpenHour && TimeHour(tokyo) < localCloseHour)
   	{
   	   ObjectSetText( "tokl", "* Tokyo:", 10, "Arial", labelMktOpenColor );
   	   ObjectSetText( "tokt", tokyos, 10, "Arial",clockMktOpenColor );
   	}
   	else
   	{
   	   ObjectSetText( "tokl", "Tokyo:", 10, "Arial", labelColor );
   	   ObjectSetText( "tokt", tokyos, 10, "Arial",clockColor );
   	}
   }
   if(ShowSydney)
   {
   	if (TimeDayOfWeek(sydney) != 0 && TimeDayOfWeek(sydney) != 6 && Highlight_Market_Open && TimeHour(sydney) >= sydneyLocalOpenHour && TimeHour(sydney) < sydneyLocalCloseHour)
   	{
   	   ObjectSetText( "sydl", "* Sydney:", 10, "Arial", labelMktOpenColor );
   	   ObjectSetText( "sydt", sydneys, 10, "Arial",clockMktOpenColor );
   	}
   	else
   	{
   	   ObjectSetText( "sydl", "Sydney:", 10, "Arial", labelColor );
   	   ObjectSetText( "sydt", sydneys, 10, "Arial",clockColor );
   	}
   }
   if(ShowAuckland)
   {
   	if (TimeDayOfWeek(auckland) != 0 && TimeDayOfWeek(auckland) != 6 && Highlight_Market_Open && TimeHour(auckland) >= localOpenHour && TimeHour(auckland) < localCloseHour)
   	{
   	   ObjectSetText( "auckl", "* Auckland:", 10, "Arial", labelMktOpenColor );
   	   ObjectSetText( "auckt", aucklands, 10, "Arial",clockMktOpenColor );
   	}
   	else
   	{
   	   ObjectSetText( "auckl", "Auckland:", 10, "Arial", labelColor );
   	   ObjectSetText( "auckt", aucklands, 10, "Arial",clockColor );
   	}
   }
   if(ShowMoscow)
   {
   	if (TimeDayOfWeek(moscow) != 0 && TimeDayOfWeek(moscow) != 6 && Highlight_Market_Open && TimeHour(moscow) >= localOpenHour && TimeHour(moscow) < localCloseHour)
   	{
   	   ObjectSetText( "mosl", "* Moscow:", 10, "Arial", labelMktOpenColor );
   	   ObjectSetText( "most", moscows, 10, "Arial",clockMktOpenColor );
   	}
   	else
   	{
   	   ObjectSetText( "mosl", "Moscow:", 10, "Arial", labelColor );
   	   ObjectSetText( "most", moscows, 10, "Arial",clockColor );
   	}
   }
   if(ShowBerlin)
   {
   	if (TimeDayOfWeek(berlin) != 0 && TimeDayOfWeek(berlin) != 6 && Highlight_Market_Open && TimeHour(berlin) >= localOpenHour && TimeHour(berlin) < localCloseHour)
   	{
   	   ObjectSetText( "berl", "* Berlin:", 10, "Arial", labelMktOpenColor );
   	   ObjectSetText( "bert", berlins, 10, "Arial",clockMktOpenColor );
   	}
   	else
   	{
   	   ObjectSetText( "berl", "Berlin:", 10, "Arial", labelColor );
   	   ObjectSetText( "bert", berlins, 10, "Arial",clockColor );
   	}
   }
   if(ShowSeattle)
   {
   	if (TimeDayOfWeek(seattle) != 0 && TimeDayOfWeek(seattle) != 6 && Highlight_Market_Open && TimeHour(seattle) >= localOpenHour && TimeHour(seattle) < localCloseHour)
   	{
   	   ObjectSetText( "seal", "* Seattle:", 10, "Arial", labelMktOpenColor );
   	   ObjectSetText( "seat", seattles, 10, "Arial",clockMktOpenColor );
   	}
   	else
   	{
   	   ObjectSetText( "seal", "Seattle:", 10, "Arial", labelColor );
   	   ObjectSetText( "seat", seattles, 10, "Arial",clockColor );
   	}
   }
   
   // Always display Broker Time
   ObjectSetText( "brol", "Broker:", 10, "Arial", labelColor );
   ObjectSetText( "brot", brokers, 10, "Arial",clockColor );
   
//----
   return(0);
  } // end of start()


//+------------------------------------------------------------------+
//| Custom functions                                                 |
//+------------------------------------------------------------------+

string TimeToString( datetime when ) {
   string timeStr;
   int hour = TimeHour( when );
   if ( !Display_Times_With_AMPM ) 
     {
      if (Display_Time_With_Seconds) timeStr = (TimeToStr( when, TIME_MINUTES|TIME_SECONDS));
      else timeStr = (TimeToStr( when, TIME_MINUTES));
     }
   else
     {
      // User wants 12HourTime format with "AM" or "PM".   
      // FYI, if >12:00, subtract 12 hours in seconds which is 12*60*60=43200
      if (Display_Time_With_Seconds)
        {
         if ( hour >  12 || hour == 0) timeStr = TimeToStr( (when - 43200), TIME_MINUTES|TIME_SECONDS);
         else timeStr = TimeToStr( when, TIME_MINUTES|TIME_SECONDS);
         if ( hour >= 12) timeStr = StringConcatenate(timeStr, " PM");
         else timeStr = StringConcatenate(timeStr, " AM");
        }
      else
        {
         if ( hour >  12 || hour == 0) timeStr = TimeToStr( (when - 43200), TIME_MINUTES);
         else timeStr = TimeToStr( when, TIME_MINUTES);
         if ( hour >= 12) timeStr = StringConcatenate(timeStr, " PM");
         else timeStr = StringConcatenate(timeStr, " AM");
        }
     }
   return (timeStr);
} // end of TimeToString
//+------------------------------------------------------------------+


int ObjectMakeLabel( string n, int xoff, int yoff ) {
   ObjectCreate( n, OBJ_LABEL, labelWindow, 0, 0 );
   ObjectSet( n, OBJPROP_CORNER, labelCorner );
   ObjectSet( n, OBJPROP_XDISTANCE, xoff );
   ObjectSet( n, OBJPROP_YDISTANCE, yoff );
   ObjectSet( n, OBJPROP_BACK, true );
} // end of ObjectMakeLabel
//+------------------------------------------------------------------+

string FormatDateTime(int nYear,int nMonth,int nDay,int nHour,int nMin,int nSec)
  {
   string sMonth,sDay,sHour,sMin,sSec;
   sMonth=100+nMonth;
   sMonth=StringSubstr(sMonth,1);
   sDay=100+nDay;
   sDay=StringSubstr(sDay,1);
   sHour=100+nHour;
   sHour=StringSubstr(sHour,1);
   sMin=100+nMin;
   sMin=StringSubstr(sMin,1);
   sSec=100+nSec;
   sSec=StringSubstr(sSec,1);
   return(StringConcatenate(nYear,".",sMonth,".",sDay," ",sHour,":",sMin,":",sSec));
} // end of FormatDateTime
//+------------------------------------------------------------------+

datetime TimeArrayToTime(int& localTimeArray[])
{
   //---- parse date and time from array
   
   int    nYear,nMonth,nDOW,nDay,nHour,nMin,nSec,nMilliSec;
   //string sMilliSec;

   nYear=localTimeArray[0]&0x0000FFFF;
   nMonth=localTimeArray[0]>>16;
   //nDOW=localTimeArray[1]&0x0000FFFF;
   nDay=localTimeArray[1]>>16;
   nHour=localTimeArray[2]&0x0000FFFF;
   nMin=localTimeArray[2]>>16;
   nSec=localTimeArray[3]&0x0000FFFF;
   nMilliSec=localTimeArray[3]>>16;
   string LocalTimeS = FormatDateTime(nYear,nMonth,nDay,nHour,nMin,nSec);
   datetime localTime = StrToTime( LocalTimeS );
   return(localTime);
} // end of TimeArrayToTime
//+------------------------------------------------------------------+

void GetAllTimeZoneInfo(int& localTZInfoArray[], int& newyorkTZInfoArray[],int& londonTZInfoArray[],int& tokyoTZInfoArray[], int& sydneyTZInfoArray[], int& aucklandTZInfoArray[], int& moscowTZInfoArray[], int& berlinTZInfoArray[], int& seattleTZInfoArray[])
{
   int dst=GetTimeZoneInformation(localTZInfoArray);
   // Note: the dst return info is no longer used.  However, FYI, the Return info is: dst =
   //  0 = Your local TZ does not switch between Std Time and DST (e.g. Tokyo, Jakarta)
   //  1 = Your local TZ does switch to DST, but is presently on ST
   //  2 = Your local TZ does switch to DST and is presently on DST
   //
   // FYI:  localTZInfoArray[n] =
   //   0 = bias, in minutes(!)    // ************* This is important and used below
   //   1-16 TZ-standard-name
   //   17-20 = StdTimeArray       // ************* This is important and used below
   //   21 = std-bias              // ************* This is important and used below
   //   22-37 = TZ-daylight-name
   //   38-41 = DaylightTimeArray  // ************* This is important and used below
   //   42 = dst-bias              // ************* This is important and used below
   
   // FYI:
   // From: http://www.tech-archive.net/Archive/DotNet/microsoft.public.dotnet.framework.interop/2005-05/msg00278.html
   //"To select the correct day in the month, set the wYear member to zero, the 
   //wHour and wMinute members to the transition time, the wDayOfWeek member to 
   //the appropriate weekday, and the wDay member to indicate the occurence of the 
   //day of the week within the month (first through fifth). 
   //
   //"Using this notation, specify the 2:00a.m. on the first Sunday in April as 
   //follows: wHour = 2, wMonth = 4, wDayOfWeek = 0, wDay = 1. Specify 2:00a.m. on 
   //the last Thursday in October as follows: wHour = 2, wMonth = 10, wDayOfWeek = 
   //4, wDay = 5."
   
   // 1<<16  = 065536 // Syntax 1<<16 is take the # and bitwise-shift it to the left 16 bits. The new (least significant) right-bits are zeros.
   // 2<<16  = 131072
   // 3<<16  = 196608
   // 4<<16  = 262144
   // 5<<16  = 327680
   // 6<<16  = 393216
   // 7<<16  = 458752
   // 8<<16  = 524288
   // 9<<16  = 589824
   // 10<<16 = 655360
   // 11<<16 = 720896
   // 12<<16 = 786432
   
   // FYI, for all the TZ ST/DST dates, the wYear=0 and wDay= the # for wDayOfWeek IN the month, e.g. wDayOfWeek=0 and wDay=1 means 1st Sunday.
   // Consequently, these numbers should be good into perpetuity, until of course, countries legistlatively change 
   // their DST/ST changeover dates. (e.g. Tokyo is considering DST, and the US changed it's dates not long ago)
   //ArrayCopy(newyorkTZInfoArray, localTZInfoArray); // Not necessary. All key fields set below.
   newyorkTZInfoArray[0] = 300;
   newyorkTZInfoArray[17] = 720896; // wYear = 0. wMonth = 11, and 11<<16 == 720896
   newyorkTZInfoArray[18] = 65536;  // wDOW = 0 = Sunday. nDay = 1 and 1<<16 == 65536 // NOTE! When wYear = 0, wDay is the # for wDOW IN the month. 1 = 1st... Sunday for example.
   newyorkTZInfoArray[19] = 2;
   newyorkTZInfoArray[20] = 0;
   newyorkTZInfoArray[21] = 0;
   newyorkTZInfoArray[38] = 196608; // 3<<16 == 196608  March
   newyorkTZInfoArray[39] = 131072; // 2<<16 == 131072  2nd Sunday
   newyorkTZInfoArray[40] = 2;
   newyorkTZInfoArray[41] = 0;
   newyorkTZInfoArray[42] = -60;
   
   londonTZInfoArray[0] = 0;
   londonTZInfoArray[17] = 655360; // 10<<16 == 655360  October
   londonTZInfoArray[18] = 327680; // 5<<16 == 327680.  5th/Last Sunday. BECAUSE this is already "5" even though in 2008 the last Sunday in Oct is the 4th Sunday, this must mean "last" Sunday.
   londonTZInfoArray[19] = 2;
   londonTZInfoArray[20] = 0;
   londonTZInfoArray[21] = 0;
   londonTZInfoArray[38] = 196608; // 3<<16 == 196608  March
   londonTZInfoArray[39] = 327680; // 5<<16 == 327680  5th/Last Sunday
   londonTZInfoArray[40] = 1;
   londonTZInfoArray[41] = 0;
   londonTZInfoArray[42] = -60;
   
   tokyoTZInfoArray[0] = -540;
   tokyoTZInfoArray[17] = 0; 
   tokyoTZInfoArray[18] = 0;
   tokyoTZInfoArray[19] = 0;
   tokyoTZInfoArray[20] = 0;
   tokyoTZInfoArray[21] = 0;
   tokyoTZInfoArray[38] = 0;
   tokyoTZInfoArray[39] = 0;
   tokyoTZInfoArray[40] = 0;
   tokyoTZInfoArray[41] = 0;
   tokyoTZInfoArray[42] = 0;
   
   sydneyTZInfoArray[0] = -600;
   sydneyTZInfoArray[17] = 262144; // 4<<16 == 262144  April
   sydneyTZInfoArray[18] = 65536;  // 1<<16 == 65536   1st Sunday
   sydneyTZInfoArray[19] = 3;
   sydneyTZInfoArray[20] = 0;
   sydneyTZInfoArray[21] = 0;
   sydneyTZInfoArray[38] = 655360; // 10<<16 == 655360  October
   sydneyTZInfoArray[39] = 65536;  // 1<<16 == 65536    1st Sunday
   sydneyTZInfoArray[40] = 2;
   sydneyTZInfoArray[41] = 0;
   sydneyTZInfoArray[42] = -60;
   
   aucklandTZInfoArray[0] = -720;
   aucklandTZInfoArray[17] = 262144; // 4<<16 == 262144  April
   aucklandTZInfoArray[18] = 65536;  // 1<<16 == 65536   1st Sunday
   aucklandTZInfoArray[19] = 3;
   aucklandTZInfoArray[20] = 0;
   aucklandTZInfoArray[21] = 0;
   aucklandTZInfoArray[38] = 589824; // 9<<16 == 589824  September
   aucklandTZInfoArray[39] = 327680; // 5<<16 == 327680  5th/Last Sunday
   aucklandTZInfoArray[40] = 2;
   aucklandTZInfoArray[41] = 0;
   aucklandTZInfoArray[42] = -60;
   
   ArrayCopy(moscowTZInfoArray, londonTZInfoArray);
   moscowTZInfoArray[0] = -180;
   
   ArrayCopy(berlinTZInfoArray, londonTZInfoArray);
   berlinTZInfoArray[0] = -60;
   
   ArrayCopy(seattleTZInfoArray, newyorkTZInfoArray);
   seattleTZInfoArray[0] = 480;
} // end of GetAllTimeZoneInfo
//+------------------------------------------------------------------+

void writeLocalTZInfoToFile(string filename, bool AllTZData)
{
   int    TimeArray[4];
   int    TZInfoArray[43];
   int    z[43];
   int dst=GetTimeZoneInformation(z);
   
   if (ObjectFind("timezone") < 0)
   {
      Alert(WindowExpertName(),": Open your Terminal window. Go to Experts tab for timezone update instructions!");
      Print(WindowExpertName(),": If the market zone ST/DST changeover dates change, or to ADD a new market zone, do these steps!");
      Print("... First check for any program updates at: http://forexfactory.com/showthread.php?t=109305");
      Print("... If no update, you can start editing the version you already have.");
      Print("... First temporarily set your CPU clock to the newyork Eastern US timezone.");
      Print("... Next create a text. Make the name 'timezone'. Make the description 'newyork'.");
      Print("... Change chart period JUST ONCE -- the file will be appended each change!");
      Print("... Repeat steps to change CPU clock and text for GMT, Tokyo, Sydney, etc.");
      Print("... Start Excel. Open a blank file. Go to Data => Import External Data => Import Data");
      Print("... Import the file: ",TerminalPath(),"\x5Cexperts\x5Cfiles\x5C",filename);
      Print("... The file is Tab delimited and should provide simple readable columns of data");
      Print("... In MetaEditor, open: ",WindowExpertName(),".mq4, search for: newyorkTZInfoArray[17]"); 
      Print("... Change all array values for all timezones according to your Excel spreadsheet");
      Print("... If you THOUGHT you just wrote data but you see this, you missed a step.");
      Print("... Check your text name/description and try again...");
      Print("... When finished... change CPU clock back to normal. Change the timezone update boolean back to FALSE");
      return(0);
   }
   string tzname = ObjectDescription("timezone");
   
   int handle;
   handle = FileOpen(filename,FILE_READ,"\t");
   if (handle<0)
   {
      // If file does not exist, open new file and write a single line with column labels and then close it.
      handle = FileOpen(filename,FILE_CSV|FILE_READ|FILE_WRITE,"\t");
      if(handle<0) 
        {
         Print(filename," OPEN Error: ",GetLastError());
         return(0);
        }
      else FileSeek(handle,0,SEEK_END);
   
      if (AllTZData) 
      {
         FileWrite(handle, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,"tzname");
      }
      else 
      {
         FileWrite(handle, 0,17,18,19,20,21,38,39,40,41,42,"tzname");
      }
      FileClose(handle);
   }
   
   // File should exist by now.
   handle = FileOpen(filename,FILE_CSV|FILE_READ|FILE_WRITE,"\t");
   if(handle<0) 
     {
      Print(filename," OPEN Error: ",GetLastError());
      return(0);
     }
   else FileSeek(handle,0,SEEK_END);
   
   if (AllTZData)
   {
      FileWrite(handle, z[0], z[1], z[2], z[3], z[4], z[5], z[6], z[7], z[8], z[9], z[10], z[11], z[12], z[13], z[14], z[15], z[16], z[17], z[18], z[19],
         z[20], z[21], z[22], z[23], z[24], z[25], z[26], z[27], z[28], z[29], z[30], z[31], z[32], z[33], z[34], z[35], z[36], z[37], z[38], z[39], z[40], z[41], z[42], tzname);
   }
   else
   {
      FileWrite(handle, z[0], z[17], z[18], z[19], z[20], z[21], z[38], z[39], z[40], z[41], z[42], tzname);
   
   }
   FileClose(handle);
   Print(WindowExpertName(),": ",tzname," data written to ",TerminalPath(),"\x5Cexperts\x5Cfiles\x5C",filename);
} // end of writeLocalTZInfoToFile


//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   if(ShowLocal)
   {
      ObjectDelete( "locl" );
      ObjectDelete( "loct" );
   }
   if(ShowNewYork)
   {
   	ObjectDelete( "nyl" );
   	ObjectDelete( "nyt" );
   }
   if(ShowUTC_GMT)
   {
	   ObjectDelete( "utcl" );
   	ObjectDelete( "utct" );
   }
   if(ShowLondon)
   {
   	ObjectDelete( "lonl" );
   	ObjectDelete( "lont" );
   }
   if(ShowTokyo)
   {
	   ObjectDelete( "tokl" );
   	ObjectDelete( "tokt" );
   }
   if(ShowSydney)
   {
	   ObjectDelete( "sydl" );
   	ObjectDelete( "sydt" );
   }
   // Broker time is always displayed so remove objects 
   ObjectDelete( "brol" );
   ObjectDelete( "brot" );
   // Bar Left time is always displayed so remove objects 
   ObjectDelete( "barl" );
   ObjectDelete( "bart" );
   if(Show_DIBS_London)
   {
   	ObjectDelete( "dibsl" );
   	ObjectDelete( "dibst" );
   }
   if(ShowAuckland)
   {
   	ObjectDelete( "auckl" );
   	ObjectDelete( "auckt" );
   }
   if(ShowMoscow)
   {
   	ObjectDelete( "mosl" );
   	ObjectDelete( "most" );
   }
   if(ShowBerlin)
   {
   	ObjectDelete( "berl" );
   	ObjectDelete( "bert" );
   }
   if(ShowSeattle)
   {
   	ObjectDelete( "seal" );
   	ObjectDelete( "seat" );
   }

//----
   return(0);
  } // end of deinit()

