Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
MM/dd/yyyy とかちょっと
* CurrentCulture 依存怖い * かと言って InvariantCulture は US 基準 * ヤードポンドの国は日付フォーマットも一味違うぜ のコンボ回避用 InterpolatedStringHandler。
- Loading branch information
Showing
5 changed files
with
157 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 34 additions & 0 deletions
34
Demo/2021/Csharp10/InterpolatedStrings/InvariantGlobalization/Invariant.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
using System.Globalization; | ||
using System.Runtime.CompilerServices; | ||
|
||
namespace InvariantGlobalization; | ||
|
||
/// <summary> | ||
/// Pass always <see cref="CultureInfo.InvariantCulture"/> to <see cref="DefaultInterpolatedStringHandler"/>. | ||
/// </summary> | ||
public static class Invariant | ||
{ | ||
public static string Format(InterpolatedStringHandler handler) => handler.ToStringAndClear(); | ||
public static string Format(Span<char> initialBuffer, [InterpolatedStringHandlerArgument("initialBuffer")] InterpolatedStringHandler handler) => handler.ToStringAndClear(); | ||
|
||
[InterpolatedStringHandler] | ||
public ref struct InterpolatedStringHandler | ||
{ | ||
private DefaultInterpolatedStringHandler _inner; | ||
|
||
public InterpolatedStringHandler(int literalLength, int formattedCount) => _inner = new(literalLength, formattedCount, CultureInfo.InvariantCulture); | ||
public InterpolatedStringHandler(int literalLength, int formattedCount, Span<char> initialBuffer) => _inner = new(literalLength, formattedCount, CultureInfo.InvariantCulture, initialBuffer); | ||
|
||
public void AppendLiteral(string value) => _inner.AppendLiteral(value); | ||
public void AppendFormatted(ReadOnlySpan<char> value) => _inner.AppendFormatted(value); | ||
public void AppendFormatted(ReadOnlySpan<char> value, int alignment = 0, string? format = null) => _inner.AppendFormatted(value, alignment, format); | ||
public void AppendFormatted<T>(T value) => _inner.AppendFormatted(value); | ||
public void AppendFormatted<T>(T value, string? format) => _inner.AppendFormatted(value, format); | ||
public void AppendFormatted<T>(T value, int alignment) => _inner.AppendFormatted(value, alignment); | ||
public void AppendFormatted<T>(T value, int alignment, string? format) => _inner.AppendFormatted(value, alignment, format); | ||
public void AppendFormatted(object? value, int alignment = 0, string? format = null) => _inner.AppendFormatted(value, alignment, format); | ||
public void AppendFormatted(string? value) => _inner.AppendFormatted(value); | ||
public void AppendFormatted(string? value, int alignment = 0, string? format = null) => _inner.AppendFormatted(value, alignment, format); | ||
public string ToStringAndClear() => _inner.ToStringAndClear(); | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
Demo/2021/Csharp10/InterpolatedStrings/InvariantGlobalization/InvariantGlobalization.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<OutputType>Exe</OutputType> | ||
<TargetFramework>net6.0</TargetFramework> | ||
<Nullable>enable</Nullable> | ||
</PropertyGroup> | ||
|
||
</Project> |
62 changes: 62 additions & 0 deletions
62
Demo/2021/Csharp10/InterpolatedStrings/InvariantGlobalization/Iso8601.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
using System.Globalization; | ||
using System.Runtime.CompilerServices; | ||
|
||
namespace InvariantGlobalization; | ||
|
||
/// <summary> | ||
/// In addition to <see cref="Invariant"/>, use ISO 8601 date format. | ||
/// </summary> | ||
/// <remarks> | ||
/// <see cref="CultureInfo.InvariantCulture"/> uses USA format which is very unique. | ||
/// | ||
/// see: | ||
/// <a href="https://en.wikipedia.org/wiki/Calendar_date#Usage_map">Calendar date: Usage map</a>, | ||
/// <a href="https://www.quora.com/Why-do-some-English-speakers-format-their-dates-as-M-D-Y-while-most-of-the-world-uses-either-D-M-Y-or-Y-M-D">Why do some English speakers format their dates as M/D/Y?</a> | ||
/// </remarks> | ||
public static class Iso8601 | ||
{ | ||
public static string Format(InterpolatedStringHandler handler) => handler.ToStringAndClear(); | ||
public static string Format(Span<char> initialBuffer, [InterpolatedStringHandlerArgument("initialBuffer")] InterpolatedStringHandler handler) => handler.ToStringAndClear(); | ||
|
||
[InterpolatedStringHandler] | ||
public ref struct InterpolatedStringHandler | ||
{ | ||
private DefaultInterpolatedStringHandler _inner; | ||
|
||
public InterpolatedStringHandler(int literalLength, int formattedCount) => _inner = new(literalLength, formattedCount, CultureInfo.InvariantCulture); | ||
public InterpolatedStringHandler(int literalLength, int formattedCount, Span<char> initialBuffer) => _inner = new(literalLength, formattedCount, CultureInfo.InvariantCulture, initialBuffer); | ||
|
||
public void AppendLiteral(string value) => _inner.AppendLiteral(value); | ||
public void AppendFormatted(ReadOnlySpan<char> value) => _inner.AppendFormatted(value); | ||
public void AppendFormatted(ReadOnlySpan<char> value, int alignment = 0, string? format = null) => _inner.AppendFormatted(value, alignment, format); | ||
public void AppendFormatted<T>(T value) => _inner.AppendFormatted(value); | ||
public void AppendFormatted<T>(T value, string? format) => _inner.AppendFormatted(value, format); | ||
public void AppendFormatted<T>(T value, int alignment) => _inner.AppendFormatted(value, alignment); | ||
public void AppendFormatted<T>(T value, int alignment, string? format) => _inner.AppendFormatted(value, alignment, format); | ||
public void AppendFormatted(object? value, int alignment = 0, string? format = null) => _inner.AppendFormatted(value, alignment, format); | ||
public void AppendFormatted(string? value) => _inner.AppendFormatted(value); | ||
public void AppendFormatted(string? value, int alignment = 0, string? format = null) => _inner.AppendFormatted(value, alignment, format); | ||
|
||
public void AppendFormatted(TimeOnly value) => _inner.AppendFormatted(value, "O"); | ||
public void AppendFormatted(TimeOnly value, string? format) => _inner.AppendFormatted(value, format ?? "O"); | ||
public void AppendFormatted(TimeOnly value, int alignment) => _inner.AppendFormatted(value, alignment, "O"); | ||
public void AppendFormatted(TimeOnly value, int alignment, string? format) => _inner.AppendFormatted(value, alignment, format ?? "O"); | ||
|
||
public void AppendFormatted(DateOnly value) => _inner.AppendFormatted(value, "O"); | ||
public void AppendFormatted(DateOnly value, string? format) => _inner.AppendFormatted(value, format ?? "O"); | ||
public void AppendFormatted(DateOnly value, int alignment) => _inner.AppendFormatted(value, alignment, "O"); | ||
public void AppendFormatted(DateOnly value, int alignment, string? format) => _inner.AppendFormatted(value, alignment, format ?? "O"); | ||
|
||
public void AppendFormatted(DateTime value) => _inner.AppendFormatted(value, "O"); | ||
public void AppendFormatted(DateTime value, string? format) => _inner.AppendFormatted(value, format ?? "O"); | ||
public void AppendFormatted(DateTime value, int alignment) => _inner.AppendFormatted(value, alignment, "O"); | ||
public void AppendFormatted(DateTime value, int alignment, string? format) => _inner.AppendFormatted(value, alignment, format ?? "O"); | ||
|
||
public void AppendFormatted(DateTimeOffset value) => _inner.AppendFormatted(value, "O"); | ||
public void AppendFormatted(DateTimeOffset value, string? format) => _inner.AppendFormatted(value, format ?? "O"); | ||
public void AppendFormatted(DateTimeOffset value, int alignment) => _inner.AppendFormatted(value, alignment, "O"); | ||
public void AppendFormatted(DateTimeOffset value, int alignment, string? format) => _inner.AppendFormatted(value, alignment, format ?? "O"); | ||
|
||
public string ToStringAndClear() => _inner.ToStringAndClear(); | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
Demo/2021/Csharp10/InterpolatedStrings/InvariantGlobalization/Program.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
using InvariantGlobalization; | ||
using System.Globalization; | ||
|
||
// CurrentCulture をあえてフランスに。 | ||
// 大陸ヨーロッパは小数点が , な事が多く。 | ||
Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-fr"); | ||
|
||
// 12,345 になるわ、 | ||
// dd/MM/yyyy になるわ。 | ||
Console.WriteLine($@"{12.345} | ||
{DateTimeOffset.Now} | ||
{new DateOnly(2000, 1, 2)} | ||
{new TimeOnly(11, 5, 30)} | ||
"); | ||
|
||
// というか、CurrentCulture 取得はそれなりにコスト(ThreadStatic アクセスあり)かかるし、 | ||
// そもそも実行環境によって Format/Parse 結果が違うのが怖い。 | ||
// なので InvariantCulture にすると… | ||
// 北米フォーマットになる。 | ||
// (IT 分野あるあるの「デフォルトは北米」。) | ||
// | ||
// MM/dd/yyyy とかちょっと… | ||
// (英語圏でも Why do Americans? とか言われてるし、他のアメリカ大陸国からは It's only USA って言われてる。 | ||
// 元々英語の語順は変だし、イギリスも古くは MM/dd/yyyy だったけど周辺国の影響で更生されてそう。 | ||
// 元植民地が宗主国よりも変化に対して保守的になるのは結構あるあるらしい。) | ||
Console.WriteLine(string.Create(CultureInfo.InvariantCulture, $@"{12.345} | ||
{DateTimeOffset.Now} | ||
{new DateOnly(2000, 1, 2)} | ||
{new TimeOnly(11, 5, 30)} | ||
")); | ||
|
||
// まあとりあえず、常時 InvariantCulture を指定するオーバーロードを作る。 | ||
Console.WriteLine(Invariant.Format($@"{12.345} | ||
{DateTimeOffset.Now} | ||
{new DateOnly(2000, 1, 2)} | ||
{new TimeOnly(11, 5, 30)} | ||
")); | ||
|
||
// で、さらに、日付フォーマットのデフォルトを O (ISO 8601 準拠)に変更。 | ||
// yyyy-MM-ddThh:mm:ss.fffffffK 相当。 | ||
Console.WriteLine(Iso8601.Format($@"{12.345} | ||
{DateTimeOffset.Now} | ||
{new DateOnly(2000, 1, 2)} | ||
{new TimeOnly(11, 5, 30)} | ||
")); |