Situation
You want to convert numeric dates to readable text with different formatting options. The Output Window is used in the example to output these strings, but string formatting can be used with string variables and any method that accepts a string as an argument.

Programming example

using System;
using System.Drawing;
using System.Linq;
using PowerLanguage.Function;

namespace PowerLanguage.Indicator
{
    [SameAsSymbol(true), UpdateOnEveryTick(false)]
    public class Example_FormattingDatesOutputWindow : IndicatorObject
    {
        public Example_FormattingDatesOutputWindow(object _ctx) : base(_ctx) { }

        private bool printOnce;

        protected override void StartCalc()
        {
            ExecInfo.MaxBarsBack = 50;
            printOnce = false;

            Output.Clear();
        }
        
        protected override void CalcBar()
        {
            if (Bars.LastBarOnChart && !printOnce)
            {
                Output.WriteLine("The current date is: {0:d/M/yyyy}",
                    DateTime.Now);

                string dateString = 
                    String.Format("Current bar date is {0:d-M-y} and 50 bars ago is {1:ddd d MMM, yyyy}",
                    Bars.Time[0],
                    Bars.Time[50]);

                Output.WriteLine(dateString);

                Output.WriteLine("Time of previous bar is " + 
                    Bars.Time[1].ToString("HH:mm:ss @ dddd d MMMM yyyy"));

                printOnce = true;
            }
        }
    }
}

Output of the programming example

The example indicator generates the following output to the Output Window:

The current date is: 14/9/2014
Current bar date is 12-9-14 and 50 bars ago is Wed 10 Sep, 2014
Time of previous bar is 22:06:00 @ Friday 12 September 2014

The PowerLanguage .NET Editor Output Window

The Output Window is the PowerLanguage .NET Editor’s tool for quickly outputting information while verifying an indicator or trading strategy. It can be used in any override method (MultiCharts, 2013) with three methods (PowerLanguage .NET Help, n.d.):

  • Output.WriteLine() and Output.Write() both print text to the Output Window, but the former also adds a line break;
  • Output.Clear() empties the Output Window.
Example of the output window in MultiCharts .NET

For more on formatting text, see composite formatting and substitution parameters, escape characters, and numeric values.

To display dates in the Output Window in any format, C#’s DateTime format strings need to be used.

DateTime and format strings in C#

The C# DateTime struct holds a range of information about a date and, optionally, a time (Dorman, 2010; Sempf, Sphar, & Davis, 2010). Two types of format strings determine how a DateTime value is converted to a string (Dorman, 2010):

  • Standard format strings contain a single character (called the format specifier) that define a more complete format string;
  • Custom format strings consist out of one or more format specifiers that define the exact string representation. They provide a great deal of flexibility.

By the way, when a single custom format specifier is used, it needs to be preceded by the percent symbol (%): otherwise, it is interpreted as a standard format specifier (Dorman, 2010).

These format strings can be used in two ways (Dorman, 2010): with the ToString() method or with composite formatting and substitution parameters. Both are used in the example.

Overview of date format specifiers in C#

An overview of the relevant format specifiers is displayed below. Note that the resulting string is dependent on the culture settings of your operating system (MSDN, n.d. b). Converting a DateTime to a string in C# can be done with the following standard and custom format specifiers (Albahari & Albahari, 2012; Dorman, 2010; MSDN, n.d. a, n.d. c):

DateTime format string Description Example (with UK English culture settings)
Standard format specifiers
"G" or "g" General date and time pattern.

"G" represents the short date with long time pattern, while "g" is the short date and short time pattern.
"G" returns 13 September 2014 as "13/09/2014 00:00:00"; "g" prints the same date as "13/09/2014 00:00".
"F" or "f" Full date and time pattern.

"F" represents the long date with long time pattern, while "f" is the long date with short time pattern.
"F" returns 13 September 2014 as "13 September 2014 00:00:00"; "f" prints the same date as "13 September 2014 00:00".
"D" or "d" The full date pattern.

"D" represents the long date pattern, "d" is the short date pattern.
"D" returns 13 September 2014 as "13 September 2014"; "d" prints the same date as "13/09/2014".
"M", "m" Month and day pattern. "M" and "m" return "13 September" when the date is 13 September 2014.
"U" Universal full date and time pattern.

Returns the same type of string as the "F" format specifier (long date and short time), but the DateTime value is automatically converted to UTC before it is formatted.
"U" returns "12 September 2014 22:00:00" when the DateTime is 13 September 2014 00:00 and one is in the UTC + 2 timezone.
"Y", "y" Year and month pattern. "Y" and "y" return "September 2014" when the DateTime is 13 September 2014.
Custom format specifiers
"d" The day of the month, from 1 through 31. Returns "13" when the date is 13 September 2014.
"dd" The day of the month from 01 through 31. Returns "07" when the date is 7 September 2014.
"ddd" The abbreviated name of the day of the week. Returns "Sat" when the date is 13 September 2014.
"dddd" The full name of the day of the week. Returns "Saturday" when the date is 13 September 2014.
"g" or "gg" The period or era. Returns "A.D" when the date is 13 September 2014.
"K" Time zone information. Returns "+02:00" when one is in the Western-European time zone.
"M" The month, from 1 to 12. Returns "9" when the date is 13 September 2014.
"MM" The month, from 01 to 12. Returns "09" when the date is 13 September 2014.
"MMM" The abbreviated name of the month. Returns "Sep" when the date is 13 September 2014.
"MMMM" The full name of the month. Returns "September" when the date is 13 September 2014.
"y" The year, from 0 to 99. Returns "14" when the year is 2014.
"yy" The year, from 00 to 99. Returns "04" when the year is 2004.
"yyy" The year with a minimum of three digits. Returns "2014" when the year is 2014.
"yyyy" The year as a four-digit number. Returns "2014" when the year is 2014.
"yyyyy" Displays the year as a five-digit number. Returns "02014" when the year is 2014.
"/" Returns the date separator for the current culture. "d/M" returns "13/9" when the date is 13 September and the culture setting is GB. Returns "13-9" when the culture is NL.
"string" or 'string' Literal string delimiter.

The enclosed characters are copied unchanged to the result.
"'date' d/M" returns "date 13/9" when the date is 13 September.
\ The escape character causes the next character to be interpreted as a literal character rather than a custom format specifier. "\t d/M" inserts a tab before "13/9" when the date is 13 September.
% Defines the following character as a custom format specifier; otherwise, standard format specifiers are used. "%d" prints "13" when the date is 13 September 2014. Without %, the "d" standard format specifier would have been used and the output would have been "13/09/2014".
Other All other characters are copied to the result string unchanged. "arr d/M" prints "arr 13/9" when the date is 13 September.

Any custom format specifier in the string will be automatically converted: a character string like "date" will print "13ae" when the date is 13 September. To prevent this, use the literal string delimiter.

PS:: A format string that contains more than one character (including white space) is considered a custom format string (Microsoft Developer Network [MSDN], n.d. a).

MultiCharts .NET programming example

The example begins with setting MultiCharts .NET class attributes:

[SameAsSymbol(true), UpdateOnEveryTick(false)]

Setting SameAsSymbol to true causes the indicator to be plotted on the main price chart. UpdateOnEveryTick set to false ensures that the indicator is only updated once per bar.

Variable declaration, setting MaxBarsBack and clearing the Output Window

The next part is the following:

private bool printOnce;

protected override void StartCalc()
{
    ExecInfo.MaxBarsBack = 50;
    printOnce = false;

    Output.Clear();
}

A Boolean variable (printOnce) is declared here and will be used later on to make sure that the output is only printed once.

Because the indicator references historical price bars, the MaxBarsBack are set programmatically with the ExecInfo.MaxBarsBack property (line 17). This prevents an automatic recalculation due to MaxBarsBack being set to ‘Auto-Detect’.

See what are ‘MaxBarsBack’ and how do they work? for background information on MaxBarsBack.

In the StartCalc() override method, executed at the begin of every script calculation (MultiCharts, 2013), the printOnce variable is set to false. That helps to only print the output once. The last statement in this method is the Output.Clear() method to clear the Output Window.

Outputting dates to the PowerLanguage .NET Editor Output Window

The last part is the CalcBar() method:

protected override void CalcBar()
{
    if (Bars.LastBarOnChart && !printOnce)
    {
        Output.WriteLine("The current date is: {0:d/M/yyyy}",
            DateTime.Now);

        string dateString = 
            String.Format("Current bar date is {0:d-M-y} and 50 bars ago is {1:ddd d MMM, yyyy}",
            Bars.Time[0],
            Bars.Time[50]);

        Output.WriteLine(dateString);

        Output.WriteLine("Time of previous bar is " + 
            Bars.Time[1].ToString("HH:mm:ss @ dddd d MMMM yyyy"));

        printOnce = true;
    }
}

The if statement evaluates two expressions: whether the current bar is the last on the chart (in which case the Bars.LastBarOnChart property returns true) and whether the printOnce variable is false. This last expression is tested with the logical not operator (!).

The body of the if statement consists out of several parts, that are discussed in turn below.

Outputting the current computer date in MultiCharts .NET

The current date is outputted first:

Output.WriteLine("The current date is: {0:d/M/yyyy}",
    DateTime.Now);

The string passed to the Output.WriteLine() method is generated with a substitution parameter (the zero between the braces). This is replaced (i.e., substituted) by the current computer time returned by the DateTime.Now property. This DateTime value is formatted with the d/M/yyyy format string: the day of the month (d), the number of the month (M), and the year as four-digit number (yyyy).

This statement generates the following output:

The current date is: 14/9/2014

By the way, while this example uses Output.WriteLine(), C# format specifiers can be used with any statement that accepts composite formatting (like String.Format() in lines 30-32) or the ToString() method (line 37).

Outputting the date of current and previous bars

Next the current bar data and historical bar data are outputted:

string dateString = 
    String.Format("Current bar date is {0:d-M-y} and 50 bars ago is {1:ddd d MMM, yyyy}",
    Bars.Time[0],
    Bars.Time[50]);

Output.WriteLine(dateString);

The Bars.Time property returns the closing time of a bar in DateTime format (see PowerLanguage .NET Help, n.d.), and with the indexer between square brackets ([ and ]) previous bars can be accessed.

In the dateString variable, generated with the String.Format() method and substitution parameters, the current bar time (Bars.Time[0]) uses the d-M-y format string while the time of the bar 50 bars back (Bars.Time[50]) is formatted in a more elaborative manner that even includes a comma: ddd d MMM, yyyy.

This generates the following output:

Current bar date is 12-9-14 and 50 bars ago is Wed 10 Sep, 2014

Outputting text with the ToString() method

The last part of the example uses the ToString() method:

Output.WriteLine("Time of previous bar is " + 
    Bars.Time[1].ToString("HH:mm:ss @ dddd d MMMM yyyy"));

printOnce = true;

The previous bar DateTime value is outputted here with both a date (dddd d MMMM yyyy) and time component (HH:mm:ss). This generates the following output:

Time of previous bar is 22:06:00 @ Friday 12 September 2014

The last statement sets the printOnce variable to true. This way the body of the if statement is only executed once (see the evaluation in line 25) per calculation cycle (see the StartCalc() override method, which resets this variable).

Key points

  • Date and time information is held by the DateTime struct in C#;
  • The DateTime values of price bars can be retrieved with the Bars.Time property in MultiCharts .NET;
  • DateTime values can be converted to a string with standard format strings (which contain a single character) or with custom format strings (that allow for more flexibility);
  • These format strings can either be used with composite formatting and substitution parameters or by calling the ToString() method on an object.
References

Albahari, J. & Albahari, B. (2012). C# 5.0 in a Nutshell: The Definitive Reference (5th edition). Sebastopol, CA: O’Reilly Media.

Dorman, S. (2010). Sams Teach Yourself Visual C# 2010 in 24 Hours. Indianapolis, IN (USA): Sams/Pearson Education.

Liberty, J. & MacDonald, B. (2009). Learning C# 3.0: Master the Fundamentals of C# 3.0. Sebastopol, CA: O’Reilly Media.

Microsoft Developer Network [MSDN] (n.d. a). Standard Date and Time Format Strings. Retrieved on September 13, 2014, from http://msdn.microsoft.com/en-us/library/az4se3k1%28v=vs.110%29.aspx

MSDN (n.d. b). DateTime Structure. Retrieved on September 13, 2014, from http://msdn.microsoft.com/en-us/library/system.datetime%28v=vs.110%29.aspx

MSDN (n.d. c). Custom Date and Time Format Strings. Retrieved on September 14, 2014, from http://msdn.microsoft.com/en-us/library/8kb3ddd4%28v=vs.110%29.aspx

MultiCharts (2013). MultiCharts .NET Programming Guide (version 1.0). Retrieved from http://www.multicharts.com/downloads/MultiCharts.NET-ProgrammingGuide-v1.0.pdf

PowerLanguage .NET Help (n.d.). Retrieved on May 16, 2014, from http://www.multicharts.com/downloads/PowerLanguage.NET.chm

Sempf, B., Sphar, C., & Davis, S.R. (2010). C# 2010 All-In-One for Dummies. Hoboken, NJ: John Wiley & Sons.

Stellman, A. & Greene, J. (2010). Head First C#: A Brain-Friendly Guide (2nd edition). Sebastopol, CA: O’Reilly Media.