From 503e70c705f7ad1024f540dea737036ca2a92e65 Mon Sep 17 00:00:00 2001 From: Genevieve Warren Date: Wed, 20 May 2020 18:45:59 -0700 Subject: [PATCH] Add datetime.parse and string.format C# samples (#3598) * add datetime.parse and string.format samples --- csharp/api/datetime.parse/Program.cs | 72 ++++++++ csharp/api/datetime.parse/README.md | 33 ++++ .../api/datetime.parse/datetime.parse.csproj | 8 + csharp/api/datetime.parse/parse_st_ifmt.cs | 66 +++++++ .../datetime.parse/parse_st_ifmt_dtstyles.cs | 95 ++++++++++ csharp/api/datetime.parse/parse_string.cs | 66 +++++++ csharp/api/datetime.parse/returnvalue.cs | 23 +++ .../api/datetime.parse/string-to-be-parsed.cs | 42 +++++ csharp/api/datetime.parse/styleflag.cs | 43 +++++ csharp/api/string.format/Program.cs | 93 ++++++++++ csharp/api/string.format/README.md | 33 ++++ .../string.format/customer-acct-formatter.cs | 77 ++++++++ csharp/api/string.format/examples.cs | 169 ++++++++++++++++++ csharp/api/string.format/format-elements.cs | 68 +++++++ csharp/api/string.format/get-started.cs | 88 +++++++++ csharp/api/string.format/q-a.cs | 122 +++++++++++++ .../string.format/roman-numeral-formatter.cs | 118 ++++++++++++ .../string.format.examples.csproj | 8 + 18 files changed, 1224 insertions(+) create mode 100644 csharp/api/datetime.parse/Program.cs create mode 100644 csharp/api/datetime.parse/README.md create mode 100644 csharp/api/datetime.parse/datetime.parse.csproj create mode 100644 csharp/api/datetime.parse/parse_st_ifmt.cs create mode 100644 csharp/api/datetime.parse/parse_st_ifmt_dtstyles.cs create mode 100644 csharp/api/datetime.parse/parse_string.cs create mode 100644 csharp/api/datetime.parse/returnvalue.cs create mode 100644 csharp/api/datetime.parse/string-to-be-parsed.cs create mode 100644 csharp/api/datetime.parse/styleflag.cs create mode 100644 csharp/api/string.format/Program.cs create mode 100644 csharp/api/string.format/README.md create mode 100644 csharp/api/string.format/customer-acct-formatter.cs create mode 100644 csharp/api/string.format/examples.cs create mode 100644 csharp/api/string.format/format-elements.cs create mode 100644 csharp/api/string.format/get-started.cs create mode 100644 csharp/api/string.format/q-a.cs create mode 100644 csharp/api/string.format/roman-numeral-formatter.cs create mode 100644 csharp/api/string.format/string.format.examples.csproj diff --git a/csharp/api/datetime.parse/Program.cs b/csharp/api/datetime.parse/Program.cs new file mode 100644 index 00000000000..db42124fde1 --- /dev/null +++ b/csharp/api/datetime.parse/Program.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; + +class ParseExamples +{ + private static readonly KeyValuePair[] examples; + private static string msg = null; + + static ParseExamples() + { + examples = new KeyValuePair[] { + new KeyValuePair(" 1. Forms of the string to be parsed", Strings.Parse), + new KeyValuePair(" 2. Return value: The DateTime.Kind property", ReturnValue.Kind), + new KeyValuePair(" 3. StyleFlags.RoundtripKind: Round-tripping a DateTime value", StyleFlag.RoundtripKind), + new KeyValuePair(" 4. DateTime.Parse(String) overload", DateTimeParse1.ParseWithSingleArg), + new KeyValuePair(" 5. DateTime.Parse(String, IFormatProvider) overload", DateTimeParse2.ParseWithTwoArgs), + new KeyValuePair(" 6. DateTime.Parse(String, IFormatProvider, DateTimeStyles) overload", DateTimeParse3.ParseWithThreeArgs) }; + } + + static void Main() + { + do + { + var choice = GetSelection(msg); + + // Make sure this parses. + bool success = Int32.TryParse(choice, out var nChoice); + msg = ""; + + if (!success) + { + msg = $"'{choice}' is not a number between 0 and {examples.Length}."; + } + else + { + if (nChoice == 0) + { + return; + } + else if (nChoice < 0 || nChoice > examples.Length) + { + msg = $"Your selection must be between 0 and {examples.Length}."; + } + else + { + Console.WriteLine(); + examples[--nChoice].Value(); + + Console.Write("\nPress any key to continue..."); + Console.ReadKey(false); + } + + } + } while (true); + } + + private static string GetSelection(string msg) + { + Console.Clear(); + Console.WriteLine(); + foreach (var example in examples) + Console.WriteLine(example.Key); + + if (!String.IsNullOrEmpty(msg)) + Console.WriteLine($"\n** {msg} **\n"); + + Console.Write("\nEnter the number of the example you wish to run and then press . Or, press 0 to exit. "); + var choice = Console.ReadLine(); + + return choice; + } +} \ No newline at end of file diff --git a/csharp/api/datetime.parse/README.md b/csharp/api/datetime.parse/README.md new file mode 100644 index 00000000000..20e5fcede04 --- /dev/null +++ b/csharp/api/datetime.parse/README.md @@ -0,0 +1,33 @@ +--- +languages: + - csharp +products: + - dotnet + - dotnet-core +page_type: sample +name: DateTime.Parse examples +urlFragment: datetime-parse +description: "A .NET Core console application that contains different examples of using the DateTime.Parse method overloads." +--- +# DateTime.Parse examples + +This sample code is a .NET Core console application written in C#. It presents numbered options to the user that correspond to different date and time parsing examples. + +## Sample prerequisites + +This sample is written in C# and targets .NET Core 3.1. It requires the [.NET Core 3.1 SDK](https://dotnet.microsoft.com/download/dotnet-core/3.1). + +## Build the sample + +The source code includes an MSBuild project file for C# (a *.csproj* file) that targets .NET Core 3.1. After you download the *.zip* file containing the example code, create a directory and select **Download ZIP** to download the sample code files to your computer. + +To build the sample: + +1. Download the *.zip* file. +1. Extrat the files in the *.zip* file to a directory of your choice. +1. If you're using Visual Studio 2019: + 1. In Visual Studio, select **Open a project or solution** on the Start page. Or, select **File** > **Open** > **Project/Solution** from the top menu. + 1. Select **Debug** > **Start Debugging** from the top menu to build and launch the application. +1. If you're working from the command line: + 1. Navigate to the directory that contains the sample. + 1. Enter the command `dotnet run` to build and launch the application. diff --git a/csharp/api/datetime.parse/datetime.parse.csproj b/csharp/api/datetime.parse/datetime.parse.csproj new file mode 100644 index 00000000000..c73e0d1692a --- /dev/null +++ b/csharp/api/datetime.parse/datetime.parse.csproj @@ -0,0 +1,8 @@ + + + + Exe + netcoreapp3.1 + + + diff --git a/csharp/api/datetime.parse/parse_st_ifmt.cs b/csharp/api/datetime.parse/parse_st_ifmt.cs new file mode 100644 index 00000000000..7ea12828bdc --- /dev/null +++ b/csharp/api/datetime.parse/parse_st_ifmt.cs @@ -0,0 +1,66 @@ +using System; +using System.Globalization; + +public class DateTimeParse2 +{ + public static void ParseWithTwoArgs() + { + // Assume the current culture is en-US. + // The date is February 16, 2008, 12 hours, 15 minutes and 12 seconds. + + // Use standard en-US date and time value. + DateTime dateValue; + string dateString = "2/16/2008 12:15:12 PM"; + try + { + dateValue = DateTime.Parse(dateString); + Console.WriteLine("'{0}' converted to {1}.", dateString, dateValue); + } + catch (FormatException) + { + Console.WriteLine("Unable to convert '{0}'.", dateString); + } + + // Reverse month and day to conform to the fr-FR culture. + // The date is February 16, 2008, 12 hours, 15 minutes and 12 seconds. + dateString = "16/02/2008 12:15:12"; + try + { + dateValue = DateTime.Parse(dateString); + Console.WriteLine("'{0}' converted to {1}.", dateString, dateValue); + } + catch (FormatException) + { + Console.WriteLine("Unable to convert '{0}'.", dateString); + } + + // Call another overload of Parse to successfully convert string + // formatted according to conventions of fr-FR culture. + try + { + dateValue = DateTime.Parse(dateString, new CultureInfo("fr-FR", false)); + Console.WriteLine("'{0}' converted to {1}.", dateString, dateValue); + } + catch (FormatException) + { + Console.WriteLine("Unable to convert '{0}'.", dateString); + } + + // Parse string with date but no time component. + dateString = "2/16/2008"; + try + { + dateValue = DateTime.Parse(dateString); + Console.WriteLine("'{0}' converted to {1}.", dateString, dateValue); + } + catch (FormatException) + { + Console.WriteLine("Unable to convert '{0}'.", dateString); + } + } +} +// The example displays the following output to the console: +// '2/16/2008 12:15:12 PM' converted to 2/16/2008 12:15:12 PM. +// Unable to convert '16/02/2008 12:15:12'. +// '16/02/2008 12:15:12' converted to 2/16/2008 12:15:12 PM. +// '2/16/2008' converted to 2/16/2008 12:00:00 AM. diff --git a/csharp/api/datetime.parse/parse_st_ifmt_dtstyles.cs b/csharp/api/datetime.parse/parse_st_ifmt_dtstyles.cs new file mode 100644 index 00000000000..f8c84fef201 --- /dev/null +++ b/csharp/api/datetime.parse/parse_st_ifmt_dtstyles.cs @@ -0,0 +1,95 @@ +using System; +using System.Globalization; + +public class DateTimeParse3 +{ + public static void ParseWithThreeArgs() + { + string dateString; + CultureInfo culture; + DateTimeStyles styles; + DateTime result; + + // Parse a date and time with no styles. + dateString = "03/01/2009 10:00 AM"; + culture = CultureInfo.CreateSpecificCulture("en-US"); + styles = DateTimeStyles.None; + try + { + result = DateTime.Parse(dateString, culture, styles); + Console.WriteLine("{0} converted to {1} {2}.", + dateString, result, result.Kind.ToString()); + } + catch (FormatException) + { + Console.WriteLine("Unable to convert {0} to a date and time.", + dateString); + } + + // Parse the same date and time with the AssumeLocal style. + styles = DateTimeStyles.AssumeLocal; + try + { + result = DateTime.Parse(dateString, culture, styles); + Console.WriteLine("{0} converted to {1} {2}.", + dateString, result, result.Kind.ToString()); + } + catch (FormatException) + { + Console.WriteLine("Unable to convert {0} to a date and time.", dateString); + } + + // Parse a date and time that is assumed to be local. + // This time is five hours behind UTC. The local system's time zone is + // eight hours behind UTC. + dateString = "2009/03/01T10:00:00-5:00"; + styles = DateTimeStyles.AssumeLocal; + try + { + result = DateTime.Parse(dateString, culture, styles); + Console.WriteLine("{0} converted to {1} {2}.", + dateString, result, result.Kind.ToString()); + } + catch (FormatException) + { + Console.WriteLine("Unable to convert {0} to a date and time.", dateString); + } + + // Attempt to convert a string in improper ISO 8601 format. + dateString = "03/01/2009T10:00:00-5:00"; + try + { + result = DateTime.Parse(dateString, culture, styles); + Console.WriteLine("{0} converted to {1} {2}.", + dateString, result, result.Kind.ToString()); + } + catch (FormatException) + { + Console.WriteLine("Unable to convert {0} to a date and time.", dateString); + } + + // Assume a date and time string formatted for the fr-FR culture is the local + // time and convert it to UTC. + dateString = "2008-03-01 10:00"; + culture = CultureInfo.CreateSpecificCulture("fr-FR"); + styles = DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeLocal; + try + { + result = DateTime.Parse(dateString, culture, styles); + Console.WriteLine("{0} converted to {1} {2}.", + dateString, result, result.Kind.ToString()); + } + catch (FormatException) + { + Console.WriteLine("Unable to convert {0} to a date and time.", dateString); + } + } +} +// The example displays the following output to the console: +// 03/01/2009 10:00 AM converted to 3/1/2009 10:00:00 AM Unspecified. +// 03/01/2009 10:00 AM converted to 3/1/2009 10:00:00 AM Local. +// 2009/03/01T10:00:00-5:00 converted to 3/1/2009 7:00:00 AM Local. +// Unable to convert 03/01/2009T10:00:00-5:00 to a date and time. +// 2008-03-01 10:00 converted to 3/1/2008 6:00:00 PM Utc. + + diff --git a/csharp/api/datetime.parse/parse_string.cs b/csharp/api/datetime.parse/parse_string.cs new file mode 100644 index 00000000000..2f2627bb6c5 --- /dev/null +++ b/csharp/api/datetime.parse/parse_string.cs @@ -0,0 +1,66 @@ +using System; +using System.Globalization; + +public class DateTimeParse1 +{ + public static void ParseWithSingleArg() + { + // Assume the current culture is en-US. + // The date is February 16, 2008, 12 hours, 15 minutes and 12 seconds. + + // Use standard en-US date and time value. + DateTime dateValue; + string dateString = "2/16/2008 12:15:12 PM"; + try + { + dateValue = DateTime.Parse(dateString); + Console.WriteLine("'{0}' converted to {1}.", dateString, dateValue); + } + catch (FormatException) + { + Console.WriteLine("Unable to convert '{0}'.", dateString); + } + + // Reverse month and day to conform to the fr-FR culture. + // The date is February 16, 2008, 12 hours, 15 minutes and 12 seconds. + dateString = "16/02/2008 12:15:12"; + try + { + dateValue = DateTime.Parse(dateString); + Console.WriteLine("'{0}' converted to {1}.", dateString, dateValue); + } + catch (FormatException) + { + Console.WriteLine("Unable to convert '{0}'.", dateString); + } + + // Call another overload of Parse to successfully convert string + // formatted according to conventions of fr-FR culture. + try + { + dateValue = DateTime.Parse(dateString, new CultureInfo("fr-FR", false)); + Console.WriteLine("'{0}' converted to {1}.", dateString, dateValue); + } + catch (FormatException) + { + Console.WriteLine("Unable to convert '{0}'.", dateString); + } + + // Parse string with date but no time component. + dateString = "2/16/2008"; + try + { + dateValue = DateTime.Parse(dateString); + Console.WriteLine("'{0}' converted to {1}.", dateString, dateValue); + } + catch (FormatException) + { + Console.WriteLine("Unable to convert '{0}'.", dateString); + } + } +} +// The example displays the following output to the console: +// '2/16/2008 12:15:12 PM' converted to 2/16/2008 12:15:12 PM. +// Unable to convert '16/02/2008 12:15:12'. +// '16/02/2008 12:15:12' converted to 2/16/2008 12:15:12 PM. +// '2/16/2008' converted to 2/16/2008 12:00:00 AM. diff --git a/csharp/api/datetime.parse/returnvalue.cs b/csharp/api/datetime.parse/returnvalue.cs new file mode 100644 index 00000000000..1f62a24426c --- /dev/null +++ b/csharp/api/datetime.parse/returnvalue.cs @@ -0,0 +1,23 @@ +using System; + +public class ReturnValue +{ + public static void Kind() + { + string[] dateStrings = {"5/1/2008 7:34:42", + "2008-05-01T07:34:42-5:00", + "2008-05-01 7:34:42Z", + "Thu, 01 May 2008 07:34:42 GMT"}; + + foreach (string dateString in dateStrings) + { + DateTime convertedDate = DateTime.Parse(dateString); + Console.WriteLine($"Converted {dateString} to {convertedDate.Kind} time {convertedDate}"); + } + } +} + +// These calls to the DateTime.Parse method display the following output: +// Converted 2008-05-01T07:34:42-5:00 to Local time 5/1/2008 5:34:42 AM +// Converted 2008-05-01 7:34:42Z to Local time 5/1/2008 12:34:42 AM +// Converted Thu, 01 May 2008 07:34:42 GMT to Local time 5/1/2008 12:34:42 AM \ No newline at end of file diff --git a/csharp/api/datetime.parse/string-to-be-parsed.cs b/csharp/api/datetime.parse/string-to-be-parsed.cs new file mode 100644 index 00000000000..7c7ff51e2ad --- /dev/null +++ b/csharp/api/datetime.parse/string-to-be-parsed.cs @@ -0,0 +1,42 @@ +using System; + +public class Strings +{ + public static void Parse() + { + (string dateAsString, string description)[] dateInfo = { + ("08/18/2018 07:22:16", "String with a date and time component"), + ("08/18/2018", "String with a date component only"), + ("8/2018", "String with a month and year component only"), + ("8/18", "String with a month and day component only"), + ("07:22:16", "String with a time component only"), + ("7 PM", "String with an hour and AM/PM designator only"), + ("2018-08-18T07:22:16.0000000Z", "UTC string that conforms to ISO 8601"), + ("2018-08-18T07:22:16.0000000-07:00", "Non-UTC string that conforms to ISO 8601"), + ("Sat, 18 Aug 2018 07:22:16 GMT", "String that conforms to RFC 1123"), + ("08/18/2018 07:22:16 -5:00", "String with date, time, and time zone information" ) + }; + + Console.WriteLine($"Today is {DateTime.Now:d}\n"); + + foreach (var (dateAsString, description) in dateInfo) + { + Console.WriteLine($"{description + ":",-52} '{dateAsString}' --> {DateTime.Parse(dateAsString)}"); + } + } +} + +// The example displays output like the following: +// Today is 2/22/2018 +// +// String with a date and time component: '08/18/2018 07:22:16' --> 8/18/2018 7:22:16 AM +// String with a date component only: '08/18/2018' --> 8/18/2018 12:00:00 AM +// String with a month and year component only: '8/2018' --> 8/1/2018 12:00:00 AM +// String with a month and day component only: '8/18' --> 8/18/2018 12:00:00 AM +// String with a time component only: '07:22:16' --> 2/22/2018 7:22:16 AM +// String with an hour and AM/PM designator only: '7 PM' --> 2/22/2018 7:00:00 PM +// UTC string that conforms to ISO 8601: '2018-08-18T07:22:16.0000000Z' --> 8/18/2018 12:22:16 AM +// Non-UTC string that conforms to ISO 8601: '2018-08-18T07:22:16.0000000-07:00' --> 8/18/2018 7:22:16 AM +// String that conforms to RFC 1123: 'Sat, 18 Aug 2018 07:22:16 GMT' --> 8/18/2018 12:22:16 AM +// String with date, time, and time zone information: '08/18/2018 07:22:16 -5:00' --> 8/18/2018 5:22:16 AM + diff --git a/csharp/api/datetime.parse/styleflag.cs b/csharp/api/datetime.parse/styleflag.cs new file mode 100644 index 00000000000..4ee670cb61a --- /dev/null +++ b/csharp/api/datetime.parse/styleflag.cs @@ -0,0 +1,43 @@ +using System; +using System.Globalization; + +[assembly: CLSCompliant(true)] +public class StyleFlag +{ + public static void RoundtripKind() + { + string[] formattedDates = { "2008-09-15T09:30:41.7752486-07:00", + "2008-09-15T09:30:41.7752486Z", + "2008-09-15T09:30:41.7752486", + "2008-09-15T09:30:41.7752486-04:00", + "Mon, 15 Sep 2008 09:30:41 GMT" }; + + foreach (string formattedDate in formattedDates) + { + Console.WriteLine(formattedDate); + + DateTime roundtripDate = DateTime.Parse(formattedDate, null, DateTimeStyles.RoundtripKind); + Console.WriteLine($" With RoundtripKind flag: {roundtripDate} {roundtripDate.Kind} time."); + + DateTime noRoundtripDate = DateTime.Parse(formattedDate, null, DateTimeStyles.None); + Console.WriteLine($" Without RoundtripKind flag: {noRoundtripDate} {noRoundtripDate.Kind} time."); + } + } +} + +// The example displays the following output: +// 2008-09-15T09:30:41.7752486-07:00 +// With RoundtripKind flag: 9/15/2008 9:30:41 AM Local time. +// Without RoundtripKind flag: 9/15/2008 9:30:41 AM Local time. +// 2008-09-15T09:30:41.7752486Z +// With RoundtripKind flag: 9/15/2008 9:30:41 AM Utc time. +// Without RoundtripKind flag: 9/15/2008 2:30:41 AM Local time. +// 2008-09-15T09:30:41.7752486 +// With RoundtripKind flag: 9/15/2008 9:30:41 AM Unspecified time. +// Without RoundtripKind flag: 9/15/2008 9:30:41 AM Unspecified time. +// 2008-09-15T09:30:41.7752486-04:00 +// With RoundtripKind flag: 9/15/2008 6:30:41 AM Local time. +// Without RoundtripKind flag: 9/15/2008 6:30:41 AM Local time. +// Mon, 15 Sep 2008 09:30:41 GMT +// With RoundtripKind flag: 9/15/2008 9:30:41 AM Utc time. +// Without RoundtripKind flag: 9/15/2008 2:30:41 AM Local time. diff --git a/csharp/api/string.format/Program.cs b/csharp/api/string.format/Program.cs new file mode 100644 index 00000000000..87a1f73b4eb --- /dev/null +++ b/csharp/api/string.format/Program.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; + +class FormatExamples +{ + private static readonly KeyValuePair[] examples; + private static string msg = null; + + static FormatExamples() + { + examples = new KeyValuePair[] { + new KeyValuePair(" 1. Get Started: Insert an object into a string", GetStarted.Example1), + new KeyValuePair(" 2. Get Started: Inserting a formatted object into a string", GetStarted.Example2), + new KeyValuePair(" 3. Get Started: Format item and object", GetStarted.Example3), + new KeyValuePair(" 4. Get Started: 2 format items and 2 objects", GetStarted.Example4), + new KeyValuePair(" 5. Get Started: Control formatting", GetStarted.Example5), + new KeyValuePair(" 6. Get Started: Control spacing", GetStarted.Example6), + new KeyValuePair(" 7: Get Started: Control alignment", GetStarted.Example7), + new KeyValuePair(" 8: Format Elements: in brief", FormatElements.FormatMethod), + new KeyValuePair(" 9: Format Elements: format item", FormatElements.FormatItem), + new KeyValuePair("10: Format Elements: Formatted format item", FormatElements.FormattedFormatItem), + new KeyValuePair("11: Format Elements: Format items with the same index", FormatElements.SameIndex), + new KeyValuePair("12: Custom Formatting: Customer account formatter", CustomerFormatterTest.Test), + new KeyValuePair("13: Custom Formatting: Roman numeral formatter", RomanNumeralExample.Test), + new KeyValuePair("14: Q & A: String interpolation comparison", QA.WithoutInterpolation), + new KeyValuePair("15: Q & A: Digits after the decimal separator", QA.DecimalDigits), + new KeyValuePair("16: Q & A: Digits after the decimal separator with custom format string", + QA.DigitsUsingCustomFormatSpecifier), + new KeyValuePair("17: Q & A: Integral digits", QA.IntegralDigits), + new KeyValuePair("18: Q & A: Integral digits with a custom format string", QA.IntegralDigitsUsingCustom), + new KeyValuePair("19: Q & A: Escaped braces", QA.EscapedBraces), + new KeyValuePair("20: Q & A: Braces in a format list", QA.BracesInFormatList), + new KeyValuePair("21: Q & A: Parameter Arrays and FormatExceptions", QA.FormatException), + new KeyValuePair("22: Examples: Format a single argument", Examples.SingleArgument), + new KeyValuePair("23: Examples: Format two arguments", Examples.TwoArguments), + new KeyValuePair("24: Examples: Format three arguments", Examples.ThreeArguments), + new KeyValuePair("25: Examples: Format more than three arguments #1", Examples.MoreThanThree_1), + new KeyValuePair("26: Examples: Format more than three arguments #2", Examples.MoreThanThree_2), + new KeyValuePair("27: Examples: Culture-sensitive formatting", Examples.CultureSensitive) }; + } + + static void Main() + { + do + { + var choice = GetSelection(msg); + + // Make sure this parses. + bool success = Int32.TryParse(choice, out var nChoice); + msg = ""; + + if (!success) + { + msg = $"'{choice}' is not a number between 0 and {examples.Length}."; + } + else + { + if (nChoice == 0) + { + return; + } + else if (nChoice < 0 || nChoice > examples.Length) + { + msg = $"Your selection must be between 0 and {examples.Length}."; + } + else + { + Console.WriteLine(); + examples[--nChoice].Value(); + + Console.Write("\nPress any key to continue..."); + Console.ReadKey(false); + } + } + } while (true); + } + + private static string GetSelection(string msg) + { + Console.Clear(); + Console.WriteLine(); + foreach (var example in examples) + Console.WriteLine(example.Key); + + if (!String.IsNullOrEmpty(msg)) + Console.WriteLine($"\n** {msg} **\n"); + + Console.Write("\nEnter the number of the example you wish to run, and then press . Or, press 0 to exit. "); + var choice = Console.ReadLine(); + + return choice; + } +} \ No newline at end of file diff --git a/csharp/api/string.format/README.md b/csharp/api/string.format/README.md new file mode 100644 index 00000000000..3600fcb5293 --- /dev/null +++ b/csharp/api/string.format/README.md @@ -0,0 +1,33 @@ +--- +languages: + - csharp +products: + - dotnet + - dotnet-core +page_type: sample +name: String.Format examples +urlFragment: string-format +description: "A .NET Core console application that contains different examples of using the String.Format method overloads." +--- +# String.Format examples + +This sample code is a .NET Core console application written in C#. It presents numbered options to the user that correspond to different string formatting examples. + +## Sample prerequisites + +This sample is written in C# and targets .NET Core 3.1. It requires the [.NET Core 3.1 SDK](https://dotnet.microsoft.com/download/dotnet-core/3.1). + +## Build the sample + +The source code includes an MSBuild project file for C# (a *.csproj* file) that targets .NET Core 3.1. After you download the *.zip* file containing the example code, create a directory and select **Download ZIP** to download the sample code files to your computer. + +To build the sample: + +1. Download the *.zip* file. +1. Extrat the files in the *.zip* file to a directory of your choice. +1. If you're using Visual Studio 2019: + 1. In Visual Studio, select **Open a project or solution** on the Start page. Or, select **File** > **Open** > **Project/Solution** from the top menu. + 1. Select **Debug** > **Start Debugging** from the top menu to build and launch the application. +1. If you're working from the command line: + 1. Navigate to the directory that contains the sample. + 1. Enter the command `dotnet run` to build and launch the application. diff --git a/csharp/api/string.format/customer-acct-formatter.cs b/csharp/api/string.format/customer-acct-formatter.cs new file mode 100644 index 00000000000..dd1dc8827c6 --- /dev/null +++ b/csharp/api/string.format/customer-acct-formatter.cs @@ -0,0 +1,77 @@ +using System; + +public class CustomerFormatterTest +{ + public static void Test() + { + int acctNumber = 79203159; + Console.WriteLine(String.Format(new CustomerFormatter(), "{0}", acctNumber)); + Console.WriteLine(String.Format(new CustomerFormatter(), "{0:G}", acctNumber)); + Console.WriteLine(String.Format(new CustomerFormatter(), "{0:S}", acctNumber)); + Console.WriteLine(String.Format(new CustomerFormatter(), "{0:P}", acctNumber)); + try + { + Console.WriteLine(String.Format(new CustomerFormatter(), "{0:X}", acctNumber)); + } + catch (FormatException e) + { + Console.WriteLine(e.Message); + } + } +} + +public class CustomerFormatter : IFormatProvider, ICustomFormatter +{ + public object GetFormat(Type formatType) + { + if (formatType == typeof(ICustomFormatter)) + return this; + else + return null; + } + + public string Format(string format, + object arg, + IFormatProvider formatProvider) + { + if (!this.Equals(formatProvider)) + { + return null; + } + else + { + if (String.IsNullOrEmpty(format)) + format = "G"; + + string customerString = arg.ToString(); + if (customerString.Length < 8) + customerString = customerString.PadLeft(8, '0'); + + format = format.ToUpper(); + switch (format) + { + case "G": + return customerString.Substring(0, 1) + "-" + + customerString.Substring(1, 5) + "-" + + customerString.Substring(6); + case "S": + return customerString.Substring(0, 1) + "/" + + customerString.Substring(1, 5) + "/" + + customerString.Substring(6); + case "P": + return customerString.Substring(0, 1) + "." + + customerString.Substring(1, 5) + "." + + customerString.Substring(6); + default: + throw new FormatException($"The '{format}' format specifier is not supported."); + } + } + } +} + +// The example displays the following output: +// 7-92031-59 +// 7-92031-59 +// 7/92031/59 +// 7.92031.59 +// The 'X' format specifier is not supported. \ No newline at end of file diff --git a/csharp/api/string.format/examples.cs b/csharp/api/string.format/examples.cs new file mode 100644 index 00000000000..5ec851268b0 --- /dev/null +++ b/csharp/api/string.format/examples.cs @@ -0,0 +1,169 @@ +using System; +using System.Collections.Generic; + +public class Examples +{ + public static void SingleArgument() + { + DateTime birthdate = new DateTime(1993, 7, 28); + DateTime[] dates = { new DateTime(1993, 8, 16), + new DateTime(1994, 7, 28), + new DateTime(2000, 10, 16), + new DateTime(2003, 7, 27), + new DateTime(2007, 5, 27) }; + + foreach (DateTime dateValue in dates) + { + TimeSpan interval = dateValue - birthdate; + // Get the approximate number of years, without accounting for leap years. + int years = ((int)interval.TotalDays) / 365; + // See if adding the number of years exceeds dateValue. + string output; + if (birthdate.AddYears(years) <= dateValue) + { + output = String.Format("You are now {0} years old.", years); + Console.WriteLine(output); + } + else + { + output = String.Format("You are now {0} years old.", years - 1); + Console.WriteLine(output); + } + } + } + + // The example displays the following output: + // You are now 0 years old. + // You are now 1 years old. + // You are now 7 years old. + // You are now 9 years old. + // You are now 13 years old. + + public static void TwoArguments() + { + Dictionary temperatureInfo = new Dictionary + { + { new DateTime(2010, 6, 1, 14, 0, 0), 87.46 }, + { new DateTime(2010, 12, 1, 10, 0, 0), 36.81 } + }; + + Console.WriteLine("Temperature Information:\n"); + string output; + foreach (var item in temperatureInfo) + { + output = String.Format("Temperature at {0,8:t} on {0,9:d}: {1,5:N1}°F", + item.Key, item.Value); + Console.WriteLine(output); + } + } + + // The example displays output like the following: + // Temperature Information: + // + // Temperature at 2:00 PM on 6/1/2010: 87.5°F + // Temperature at 10:00 AM on 12/1/2010: 36.8°F + + public static void ThreeArguments() + { + string formatString = " {0,10} ({0,8:X8})\n" + + "And {1,10} ({1,8:X8})\n" + + " = {2,10} ({2,8:X8})"; + int value1 = 16932; + int value2 = 15421; + string result = String.Format(formatString, + value1, value2, value1 & value2); + Console.WriteLine(result); + } + + // The example displays the following output: + // 16932 (00004224) + // And 15421 (00003C3D) + // = 36 (00000024) + + public static void MoreThanThree_1() + { + DateTime date1 = new DateTime(2009, 7, 1); + TimeSpan hiTime = new TimeSpan(14, 17, 32); + decimal hiTemp = 62.1m; + TimeSpan loTime = new TimeSpan(3, 16, 10); + decimal loTemp = 54.8m; + + string result1 = String.Format("Temperature on {0:d}:\n{1,11}: {2} degrees (hi)\n{3,11}: {4} degrees (lo)", + date1, hiTime, hiTemp, loTime, loTemp); + Console.WriteLine(result1); + Console.WriteLine(); + + string result2 = String.Format("Temperature on {0:d}:\n{1,11}: {2} degrees (hi)\n{3,11}: {4} degrees (lo)", + new object[] { date1, hiTime, hiTemp, loTime, loTemp }); + Console.WriteLine(result2); + } + + // The example displays output like the following: + // Temperature on 7/1/2009: + // 14:17:32: 62.1 degrees (hi) + // 03:16:10: 54.8 degrees (lo) + // Temperature on 7/1/2009: + // 14:17:32: 62.1 degrees (hi) + // 03:16:10: 54.8 degrees (lo) + + public class CityInfo + { + public CityInfo(String name, int population, Decimal area, int year) + { + this.Name = name; + this.Population = population; + this.Area = area; + this.Year = year; + } + + public readonly String Name; + public readonly int Population; + public readonly Decimal Area; + public readonly int Year; + } + + public static void MoreThanThree_2() + { + CityInfo nyc2010 = new CityInfo("New York", 8175133, 302.64m, 2010); + ShowPopulationData(nyc2010); + CityInfo sea2010 = new CityInfo("Seattle", 608660, 83.94m, 2010); + ShowPopulationData(sea2010); + } + + private static void ShowPopulationData(CityInfo city) + { + object[] args = { city.Name, city.Year, city.Population, city.Area }; + String result = String.Format("{0} in {1}: Population {2:N0}, Area {3:N1} sq. feet", + args); + Console.WriteLine(result); + } + + // The example displays the following output: + // New York in 2010: Population 8,175,133, Area 302.6 sq. feet + // Seattle in 2010: Population 608,660, Area 83.9 sq. feet + + public static void CultureSensitive() + { + string[] cultureNames = { "en-US", "fr-FR", "de-DE", "es-ES" }; + + DateTime dateToDisplay = new DateTime(2009, 9, 1, 18, 32, 0); + double value = 9164.32; + + Console.WriteLine("Culture Date Value\n"); + foreach (string cultureName in cultureNames) + { + var culture = new System.Globalization.CultureInfo(cultureName); + string output = String.Format(culture, "{0,-11} {1,-35:D} {2:N}", + culture.Name, dateToDisplay, value); + Console.WriteLine(output); + } + } + + // The example displays the following output: + // Culture Date Value + // + // en-US Tuesday, September 01, 2009 9,164.32 + // fr-FR mardi 1 septembre 2009 9 164,32 + // de-DE Dienstag, 1. September 2009 9.164,32 + // es-ES martes, 01 de septiembre de 2009 9.164,32 +} \ No newline at end of file diff --git a/csharp/api/string.format/format-elements.cs b/csharp/api/string.format/format-elements.cs new file mode 100644 index 00000000000..7f97d50422d --- /dev/null +++ b/csharp/api/string.format/format-elements.cs @@ -0,0 +1,68 @@ +using System; + +public class FormatElements +{ + public static void FormatMethod() + { + DateTime dat = new DateTime(2012, 1, 17, 9, 30, 0); + string city = "Chicago"; + int temp = -16; + string output = String.Format("At {0} in {1}, the temperature was {2} degrees.", + dat, city, temp); + Console.WriteLine(output); + + // The example displays output like the following: + // At 1/17/2012 9:30:00 AM in Chicago, the temperature was -16 degrees. + } + + public static void FormatItem() + { + var value = String.Format("{0,-10:C}", 126347.89m); + Console.WriteLine(value); + } + + public static void FormattedFormatItem() + { + // Create array of 5-tuples with population data for three U.S. cities, 1940-1950. + Tuple[] cities = + { Tuple.Create("Los Angeles", new DateTime(1940, 1, 1), 1504277, + new DateTime(1950, 1, 1), 1970358), + Tuple.Create("New York", new DateTime(1940, 1, 1), 7454995, + new DateTime(1950, 1, 1), 7891957), + Tuple.Create("Chicago", new DateTime(1940, 1, 1), 3396808, + new DateTime(1950, 1, 1), 3620962), + Tuple.Create("Detroit", new DateTime(1940, 1, 1), 1623452, + new DateTime(1950, 1, 1), 1849568) }; + + // Display header + var header = String.Format("{0,-12}{1,8}{2,12}{1,8}{2,12}{3,14}\n", + "City", "Year", "Population", "Change (%)"); + Console.WriteLine(header); + foreach (var city in cities) + { + var output = String.Format("{0,-12}{1,8:yyyy}{2,12:N0}{3,8:yyyy}{4,12:N0}{5,14:P1}", + city.Item1, city.Item2, city.Item3, city.Item4, city.Item5, + (city.Item5 - city.Item3) / (double)city.Item3); + Console.WriteLine(output); + } + + // The example displays the following output: + // City Year Population Year Population Change (%) + // + // Los Angeles 1940 1,504,277 1950 1,970,358 31.0 % + // New York 1940 7,454,995 1950 7,891,957 5.9 % + // Chicago 1940 3,396,808 1950 3,620,962 6.6 % + // Detroit 1940 1,623,452 1950 1,849,568 13.9 % + } + + public static void SameIndex() + { + short[] values = { Int16.MinValue, -27, 0, 1042, Int16.MaxValue }; + Console.WriteLine("{0,10} {1,10}\n", "Decimal", "Hex"); + foreach (short value in values) + { + string formatString = String.Format("{0,10:G}: {0,10:X}", value); + Console.WriteLine(formatString); + } + } +} \ No newline at end of file diff --git a/csharp/api/string.format/get-started.cs b/csharp/api/string.format/get-started.cs new file mode 100644 index 00000000000..f739401cc46 --- /dev/null +++ b/csharp/api/string.format/get-started.cs @@ -0,0 +1,88 @@ +using System; + +public class GetStarted +{ + public static void Example1() + { + Decimal pricePerOunce = 17.36m; + String s = String.Format("The current price is {0} per ounce.", + pricePerOunce); + Console.WriteLine(s); + + // Result: The current price is 17.36 per ounce. + } + + public static void Example2() + { + Decimal pricePerOunce = 17.36m; + String s = String.Format("The current price is {0:C2} per ounce.", + pricePerOunce); + Console.WriteLine(s); + + // Result if current culture is en-US: + // The current price is $17.36 per ounce. + } + + public static void Example3() + { + decimal temp = 20.4m; + string s = String.Format("The temperature is {0}°C.", temp); + Console.WriteLine(s); + + // Displays 'The temperature is 20.4°C.' + } + + public static void Example4() + { + string s = String.Format("At {0}, the temperature is {1}°C.", + DateTime.Now, 20.4); + Console.WriteLine(s); + + // Output similar to: 'At 4/10/2015 9:29:41 AM, the temperature is 20.4°C.' + } + + public static void Example5() + { + string s = String.Format("It is now {0:d} at {0:t}", DateTime.Now); + Console.WriteLine(s); + + // Output similar to: 'It is now 4/10/2015 at 10:04 AM' + } + + public static void Example6() + { + int[] years = { 2013, 2014, 2015 }; + int[] population = { 1025632, 1105967, 1148203 }; + var sb = new System.Text.StringBuilder(); + sb.Append(String.Format("{0,6} {1,15}\n\n", "Year", "Population")); + for (int index = 0; index < years.Length; index++) + sb.Append(String.Format("{0,6} {1,15:N0}\n", years[index], population[index])); + + Console.WriteLine(sb); + + // Result: + // Year Population + // + // 2013 1,025,632 + // 2014 1,105,967 + // 2015 1,148,203 + } + + public static void Example7() + { + int[] years = { 2013, 2014, 2015 }; + int[] population = { 1025632, 1105967, 1148203 }; + String s = String.Format("{0,-10} {1,-10}\n\n", "Year", "Population"); + for (int index = 0; index < years.Length; index++) + s += String.Format("{0,-10} {1,-10:N0}\n", + years[index], population[index]); + Console.WriteLine($"\n{s}"); + + // Result: + // Year Population + // + // 2013 1,025,632 + // 2014 1,105,967 + // 2015 1,148,203 + } +} diff --git a/csharp/api/string.format/q-a.cs b/csharp/api/string.format/q-a.cs new file mode 100644 index 00000000000..0d2731d6fb8 --- /dev/null +++ b/csharp/api/string.format/q-a.cs @@ -0,0 +1,122 @@ +using System; + +public class QA +{ + public static void WithoutInterpolation() + { + Console.WriteLine("Without string interpolation (using composite formatting)\n"); + string[] names = { "Balto", "Vanya", "Dakota", "Samuel", "Koani", "Yiska", "Yuma" }; + string output = names[0] + ", " + names[1] + ", " + names[2] + ", " + + names[3] + ", " + names[4] + ", " + names[5] + ", " + + names[6]; + + output += "\n"; + var date = DateTime.Now; + output += String.Format("It is {0:t} on {0:d}. The day of the week is {1}.", + date, date.DayOfWeek); + Console.WriteLine(output); + + WithInterpolation(); + } + + private static void WithInterpolation() + { + Console.WriteLine("\nWith string interpolation\n"); + string[] names = { "Balto", "Vanya", "Dakota", "Samuel", "Koani", "Yiska", "Yuma" }; + string output = $"{names[0]}, {names[1]}, {names[2]}, {names[3]}, {names[4]}, " + + $"{names[5]}, {names[6]}"; + + var date = DateTime.Now; + output += $"\nIt is {date:t} on {date:d}. The day of the week is {date.DayOfWeek}."; + Console.WriteLine(output); + } + + public static void DecimalDigits() + { + object[] values = { 1603, 1794.68235, 15436.14 }; + string result; + foreach (var value in values) + { + result = String.Format("{0,12:C2} {0,12:E3} {0,12:F4} {0,12:N3} {1,12:P2}\n", + Convert.ToDouble(value), Convert.ToDouble(value) / 10000); + Console.WriteLine(result); + } + } + + // The example displays output like the following: + // $1,603.00 1.603E+003 1603.0000 1,603.000 16.03 % + // + // $1,794.68 1.795E+003 1794.6824 1,794.682 17.95 % + // + // $15,436.14 1.544E+004 15436.1400 15,436.140 154.36 % + + public static void DigitsUsingCustomFormatSpecifier() + { + decimal value = 16309.5436m; + string result = String.Format("{0,12:#.00000} {0,12:0,000.00} {0,12:000.00#}", + value); + Console.WriteLine(result); + } + + // The example displays the following output: + // 16309.54360 16,309.54 16309.544 + + public static void IntegralDigits() + { + int value = 1326; + string result = String.Format("{0,10:D6} {0,10:X8}", value); + Console.WriteLine(result); + } + + // The example displays the following output: + // 001326 0000052E + + public static void IntegralDigitsUsingCustom() + { + int value = 16342; + string result = String.Format("{0,18:00000000} {0,18:00000000.000} {0,18:000,0000,000.0}", + value); + Console.WriteLine(result); + } + + // The example displays the following output: + // 00016342 00016342.000 0,000,016,342.0 + + public static void EscapedBraces() + { + string result; + int nOpen = 1; + int nClose = 2; + result = String.Format("The text has {0} '{{' characters and {1} '}}' characters.", + nOpen, nClose); + Console.WriteLine(result); + } + + public static void BracesInFormatList() + { + string result; + int nOpen = 1; + int nClose = 2; + result = String.Format("The text has {0} '{1}' characters and {2} '{3}' characters.", + nOpen, "{", nClose, "}"); + Console.WriteLine(result); + } + + public static void FormatException() + { + Random rnd = new Random(); + int[] numbers = new int[4]; + int total = 0; + for (int ctr = 0; ctr <= 2; ctr++) + { + int number = rnd.Next(1001); + numbers[ctr] = number; + total += number; + } + numbers[3] = total; + object[] values = new object[numbers.Length]; + numbers.CopyTo(values, 0); + Console.WriteLine("{0} + {1} + {2} = {3}", values); + } +} + diff --git a/csharp/api/string.format/roman-numeral-formatter.cs b/csharp/api/string.format/roman-numeral-formatter.cs new file mode 100644 index 00000000000..189c6d4c27a --- /dev/null +++ b/csharp/api/string.format/roman-numeral-formatter.cs @@ -0,0 +1,118 @@ +using System; +using System.Globalization; + +public class InterceptProvider : IFormatProvider, ICustomFormatter +{ + public object GetFormat(Type formatType) + { + if (formatType == typeof(ICustomFormatter)) + return this; + else + return null; + } + + public string Format(String format, Object obj, IFormatProvider provider) + { + // Display information about method call. + string formatString = format ?? ""; + Console.WriteLine("Provider: {0}, Object: {1}, Format String: {2}", + provider.GetType().Name, obj ?? "", formatString); + + if (obj == null) return String.Empty; + + // If this is a byte and the "R" format string, format it with Roman numerals. + if (obj is Byte && formatString.ToUpper().Equals("R")) + { + Byte value = (Byte)obj; + int result; + String returnString = String.Empty; + + // Get the hundreds digit(s) + result = Math.DivRem(value, 100, out var remainder); + if (result > 0) + returnString = new String('C', result); + value = (Byte)remainder; + // Get the 50s digit + result = Math.DivRem(value, 50, out remainder); + if (result == 1) + returnString += "L"; + value = (Byte)remainder; + // Get the tens digit. + result = Math.DivRem(value, 10, out remainder); + if (result > 0) + returnString += new String('X', result); + value = (Byte)remainder; + // Get the fives digit. + result = Math.DivRem(value, 5, out remainder); + if (result > 0) + returnString += "V"; + // Add the ones digit. + if (remainder > 0) + returnString += new String('I', remainder); + + // Check whether we have too many X characters. + int pos = returnString.IndexOf("XXXX"); + if (pos >= 0) + { + int xPos = returnString.IndexOf("L"); + if (xPos >= 0 & xPos == pos - 1) + returnString = returnString.Replace("LXXXX", "XC"); + else + returnString = returnString.Replace("XXXX", "XL"); + } + // Check whether we have too many I characters + pos = returnString.IndexOf("IIII"); + if (pos >= 0) + if (returnString.IndexOf("V") >= 0) + returnString = returnString.Replace("VIIII", "IX"); + else + returnString = returnString.Replace("IIII", "IV"); + + return returnString; + } + + // Use default for all other formatting. + if (obj is IFormattable) + return ((IFormattable)obj).ToString(format, CultureInfo.CurrentCulture); + else + return obj.ToString(); + } +} + +public class RomanNumeralExample +{ + public static void Test() + { + int n = 10; + double value = 16.935; + DateTime day = DateTime.Now; + InterceptProvider provider = new InterceptProvider(); + Console.WriteLine(String.Format(provider, "{0:N0}: {1:C2} on {2:d}\n", n, value, day)); + Console.WriteLine(String.Format(provider, "{0}: {1:F}\n", "Today: ", + (DayOfWeek)DateTime.Now.DayOfWeek)); + Console.WriteLine(String.Format(provider, "{0:X}, {1}, {2}\n", + (Byte)2, (Byte)12, (Byte)199)); + Console.WriteLine(String.Format(provider, "{0:R}, {1:R}, {2:R}\n", + (Byte)2, (Byte)12, (Byte)199)); + } +} + +// The example displays the following output: +// Provider: InterceptProvider, Object: 10, Format String: N0 +// Provider: InterceptProvider, Object: 16.935, Format String: C2 +// Provider: InterceptProvider, Object: 1/31/2013 6:10:28 PM, Format String: d +// 10: $16.94 on 1/31/2013 +// +// Provider: InterceptProvider, Object: Today: , Format String: +// Provider: InterceptProvider, Object: Thursday, Format String: F +// Today: : Thursday +// +// Provider: InterceptProvider, Object: 2, Format String: X +// Provider: InterceptProvider, Object: 12, Format String: +// Provider: InterceptProvider, Object: 199, Format String: +// 2, 12, 199 +// +// Provider: InterceptProvider, Object: 2, Format String: R +// Provider: InterceptProvider, Object: 12, Format String: R +// Provider: InterceptProvider, Object: 199, Format String: R +// II, XII, CXCIX \ No newline at end of file diff --git a/csharp/api/string.format/string.format.examples.csproj b/csharp/api/string.format/string.format.examples.csproj new file mode 100644 index 00000000000..ce1697ae883 --- /dev/null +++ b/csharp/api/string.format/string.format.examples.csproj @@ -0,0 +1,8 @@ + + + + Exe + netcoreapp2.0 + + +