diff --git a/snippets/fsharp/System/IFormatProvider/Overview/Provider.fs b/snippets/fsharp/System/IFormatProvider/Overview/Provider.fs new file mode 100644 index 00000000000..05e3234f5a8 --- /dev/null +++ b/snippets/fsharp/System/IFormatProvider/Overview/Provider.fs @@ -0,0 +1,91 @@ +module Provider + +// +open System +open System.Globalization + +type AcctNumberFormat() = + let [] ACCT_LENGTH = 12 + + interface IFormatProvider with + member this.GetFormat(formatType: Type) = + if formatType = typeof then + this + else + null + + interface ICustomFormatter with + member this.Format(fmt: string, arg: obj, formatProvider: IFormatProvider) = + // Provide default formatting if arg is not an Int64. + // Provide default formatting for unsupported format strings. + let ufmt = fmt.ToUpper CultureInfo.InvariantCulture + if arg.GetType() = typeof && (ufmt = "H" || ufmt = "I") then + // Convert argument to a string. + let result = string arg + + let result = + // If account number is less than 12 characters, pad with leading zeroes. + if result.Length < ACCT_LENGTH then + result.PadLeft(ACCT_LENGTH, '0') + else result + + let result = + // If account number is more than 12 characters, truncate to 12 characters. + if result.Length > ACCT_LENGTH then + result.Substring(0, ACCT_LENGTH) + else result + + // Integer-only format. + if ufmt = "I" then + result + // Add hyphens for H format specifier. + else // Hyphenated format. + result.Substring(0, 5) + "-" + result.Substring(5, 3) + "-" + result.Substring(8) + else + try + this.HandleOtherFormats(fmt, arg) + with :? FormatException as e -> + raise (FormatException($"The format of '{fmt}' is invalid.", e)) + + member _.HandleOtherFormats(format: string, arg: obj) = + match arg with + | :? IFormattable as arg -> + arg.ToString(format, CultureInfo.CurrentCulture) + | null -> + string arg + | _ -> + String.Empty +// + + +// +open System +open System.Globalization + +type DaysOfWeek = Monday = 1 | Tuesday = 2 + +[] +let main _ = + let acctNumber = 104254567890L + let balance = 16.34 + let wday = DaysOfWeek.Monday + + let output = + String.Format(AcctNumberFormat(), + "On {2}, the balance of account {0:H} was {1:C2}.", + acctNumber, balance, wday) + printfn $"{output}" + + let wday = DaysOfWeek.Tuesday + let output = + String.Format(AcctNumberFormat(), + "On {2}, the balance of account {0:I} was {1:C2}.", + acctNumber, balance, wday) + printfn $"{output}" + 0 + +// The example displays the following output: +// On Monday, the balance of account 10425-456-7890 was $16.34. +// On Tuesday, the balance of account 104254567890 was $16.34. +// + diff --git a/snippets/fsharp/System/IFormatProvider/Overview/fs.fsproj b/snippets/fsharp/System/IFormatProvider/Overview/fs.fsproj new file mode 100644 index 00000000000..db126a32855 --- /dev/null +++ b/snippets/fsharp/System/IFormatProvider/Overview/fs.fsproj @@ -0,0 +1,11 @@ + + + Exe + net6.0 + + + + + + + \ No newline at end of file diff --git a/snippets/fsharp/System/IFormatProvider/Overview/provider2.fs b/snippets/fsharp/System/IFormatProvider/Overview/provider2.fs new file mode 100644 index 00000000000..aeb15b14724 --- /dev/null +++ b/snippets/fsharp/System/IFormatProvider/Overview/provider2.fs @@ -0,0 +1,21 @@ +module provider2 + +// +open System +open System.Globalization + +let dateValue = DateTime(2009, 6, 1, 16, 37, 0) +let cultures = + [ CultureInfo "en-US" + CultureInfo "fr-FR" + CultureInfo "it-IT" + CultureInfo "de-DE" ] + +for culture in cultures do + printfn $"{culture.Name}: {dateValue.ToString culture}" +// The example displays the following output: +// en-US: 6/1/2009 4:37:00 PM +// fr-FR: 01/06/2009 16:37:00 +// it-IT: 01/06/2009 16.37.00 +// de-DE: 01.06.2009 16:37:00 +// \ No newline at end of file diff --git a/xml/System/IFormatProvider.xml b/xml/System/IFormatProvider.xml index c077d1af488..1ee099335ce 100644 --- a/xml/System/IFormatProvider.xml +++ b/xml/System/IFormatProvider.xml @@ -69,16 +69,19 @@ The following example illustrates how an implementation can change the representation of a date and time value. In this case, a single date is displayed by using objects that represent four different cultures. :::code language="csharp" source="~/snippets/csharp/System/IFormatProvider/Overview/provider2.cs" interactive="try-dotnet" id="Snippet3"::: + :::code language="fsharp" source="~/snippets/fsharp/System/IFormatProvider/Overview/provider2.fs" id="Snippet3"::: :::code language="vb" source="~/snippets/visualbasic/VS_Snippets_CLR_System/system.IFormatProvider.Class/vb/provider2.vb" id="Snippet3"::: The following example illustrates the use of a class that implements the interface and the method. The `AcctNumberFormat` class converts an value that represents an account number to a formatted 12-digit account number. Its `GetFormat` method returns a reference to the current `AcctNumberFormat` instance if the `formatType` parameter refers to a class that implements ; otherwise, `GetFormat` returns `null`. :::code language="csharp" source="~/snippets/csharp/System/IFormatProvider/Overview/Provider.cs" id="Snippet2"::: + :::code language="fsharp" source="~/snippets/fsharp/System/IFormatProvider/Overview/Provider.fs" id="Snippet2"::: :::code language="vb" source="~/snippets/visualbasic/VS_Snippets_CLR_System/system.IFormatProvider.Class/vb/Provider.vb" id="Snippet2"::: The class that implements can then be used in a call to a formatting and parsing operation. For example, the following code calls the method to generate a string that contains a formatted 12-digit account number. :::code language="csharp" source="~/snippets/csharp/System/IFormatProvider/Overview/Provider.cs" id="Snippet1"::: + :::code language="fsharp" source="~/snippets/fsharp/System/IFormatProvider/Overview/Provider.fs" id="Snippet1"::: :::code language="vb" source="~/snippets/visualbasic/VS_Snippets_CLR_System/system.IFormatProvider.Class/vb/Provider.vb" id="Snippet1"::: ]]> @@ -148,11 +151,13 @@ The following example illustrates the use of a class that implements the interface and the method. The `AcctNumberFormat` class converts an value that represents an account number to a formatted 12-digit account number. Its `GetFormat` method returns a reference to itself if the `formatType` parameter refers to a class that implements ; otherwise, `GetFormat` returns `null`. :::code language="csharp" source="~/snippets/csharp/System/IFormatProvider/Overview/Provider.cs" id="Snippet2"::: + :::code language="fsharp" source="~/snippets/fsharp/System/IFormatProvider/Overview/Provider.fs" id="Snippet2"::: :::code language="vb" source="~/snippets/visualbasic/VS_Snippets_CLR_System/system.IFormatProvider.Class/vb/Provider.vb" id="Snippet2"::: An instance of the `AcctNumberFormat` class can then be passed as an argument to a method that provides formatting or parsing services. For example, the following code passes an `AcctNumberFormat` class to the method to generate a formatted 12-digit account number. :::code language="csharp" source="~/snippets/csharp/System/IFormatProvider/Overview/Provider.cs" id="Snippet1"::: + :::code language="fsharp" source="~/snippets/fsharp/System/IFormatProvider/Overview/Provider.fs" id="Snippet1"::: :::code language="vb" source="~/snippets/visualbasic/VS_Snippets_CLR_System/system.IFormatProvider.Class/vb/Provider.vb" id="Snippet1"::: ]]>