Kir*_*lac 5 c# formatting datetime
我有一个 DateTime 对象,我试图将其输出到符合 ISO 8601 的格式的 xml 文件中,以便在两个系统之间传输 - 我们无法控制接收者。.net往返格式在很大程度上满足了这一要求,但将精度强制要求为 7dp。
有什么方法可以指定这个吗?例如,"o:0"完全省略毫秒小数位或"o:3"将其设置为 3dp。yyyy'-'MM'-'dd'T'HH':'mm':'ssK我知道我可以自己使用(或分别)作为自定义格式说明符来格式化输出,yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffK以在必要时控制小数位,但想看看我是否错过了一种简单地将小数精度传递给格式"o"说明符的方法。
看来答案是否定的,没有任何东西(至少在核心框架中)可以自定义它。查看往返格式的源代码,DateTime它被硬编码为 7dp:
// Omitted for brevity
...
AppendHHmmssTimeOfDay(result, dateTime);
result.Append('.');
long fraction = dateTime.Ticks % TimeSpan.TicksPerSecond;
AppendNumber(result, fraction, 7);
Run Code Online (Sandbox Code Playgroud)
如果有人感兴趣,我的解决方案是实现一种自定义ToFormattedString()扩展方法来处理此问题,如果需要,它将用自定义的格式字符串替换格式字符串,并使用ToString该方法进行调用:
using System.Globalization; // System.Globalization needed for IFormatProvider overload
using System.Text; // System.Text required for StringBuilder class
namespace Extensions
{
public static class DateTimeFormatExtension
{
// Consts for building the custom format string
private const string ROUNDTRIP_FORMAT_PREFIX = "yyyy'-'MM'-'dd'T'HH':'mm':'ss";
private const char ROUNDTRIP_FORMAT_FRACTION = 'f';
private const char ROUNDTRIP_FORMAT_SUFFIX = 'K';
// Appending the 'f' custom format string maxes out at "fffffff"(7 dp) and will throw an exception if given more
private const int DATETIME_MAX_DP = 7;
private static int GetRoundtripLength(int decimalPlaces) =>
ROUNDTRIP_FORMAT_PREFIX.Length + decimalPlaces + 2; // +2 to account for the '.' and the 'K' suffix
public static string ToFormattedString(this DateTime input) => input.ToString();
public static string ToFormattedString(this DateTime input, string format)
{
var provider = DateTimeFormatInfo.CurrentInfo;
return input.ToFormattedString(format, provider);
}
public static string ToFormattedString(this DateTime input, string format, IFormatProvider provider)
{
string parsedFormat = format;
if (!string.IsNullOrWhiteSpace(format))
{
switch (format[0])
{
case 'o':
case 'O':
var precision = format.Substring(1);
// Only do this if we have a custom 'o' string, otherwise us the base functionality
if (!string.IsNullOrWhiteSpace(precision))
{
// If the custom addition to the format string is an integer, use that to determine dp
if (int.TryParse(precision, out int decimalCount))
{
// Build the format string
var formatBuilder = new StringBuilder(GetRoundtripLength(decimalCount));
formatBuilder.Append(ROUNDTRIP_FORMAT_PREFIX);
// Append '.' and 'f' chars to format string (Append nothing if 0 dp)
if (decimalCount > 0)
{
formatBuilder
.Append('.')
.Append(ROUNDTRIP_FORMAT_FRACTION,
// Cap max dp length to avoid exceptions
Math.Min(decimalCount, DATETIME_MAX_DP));
}
// Append 'K' suffix
formatBuilder.Append(ROUNDTRIP_FORMAT_SUFFIX);
parsedFormat = formatBuilder.ToString();
}
}
break;
default:
break;
}
}
return input.ToString(parsedFormat, provider);
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后可以这样使用:
using Extensions;
...
DateTime currentDateTime = DateTime.UtcNow;
string result;
result = currentDateTime.ToFormattedString(); // empty just calls the default ToString()
// result: "2018-03-02 12:31:17 AM"
result = currentDateTime.ToFormattedString("dd/MM/yy ssmmhh"); // custom format strings still work
// result: "02-03-18 173112"
result = currentDateTime.ToFormattedString("d"); // standard format strings still work
// result: "2018-03-02"
result = currentDateTime.ToFormattedString("D");
// result: "Friday, March 2, 2018"
result = currentDateTime.ToFormattedString("F");
// result: "Friday, March 2, 2018 12:31:17 AM"
result = currentDateTime.ToFormattedString("o"); // standard format specifier uses default ToString("o") behaviour
// result: "2018-03-02T00:31:17.9818727Z"
result = currentDateTime.ToFormattedString("o0"); // no decimal places
// result: "2018-03-02T00:31:17Z"
result = currentDateTime.ToFormattedString("o3"); // 3 decimal places
// result: "2018-03-02T00:31:17.981Z"
result = currentDateTime.ToFormattedString("o100"); // too many decimals cap at 7
// result: "2018-03-02T00:31:17.9818727Z"
Run Code Online (Sandbox Code Playgroud)
编辑:更新以从格式字符串中删除“:”,以与在数字格式上指定小数精度的方式保持一致:
标准数字格式字符串采用 形式
Axx,其中:
A是一个称为格式说明符的字母字符。
...
xx是一个可选整数,称为精度说明符