如何最好地获取格式化字符串以表示UTC偏移量?

11

我需要将日期格式化为以下形式:20110202192008-0500。以下代码可以实现,但我想知道在 c# 3.5 中是否有更好/更简洁的方法。谢谢!

  var date = DateTime.Now;
  var strDate = TimeZoneInfo.ConvertTimeToUtc(date).ToString("yyyyMMddHHmmss");
  var offsetHours = TimeZoneInfo.Local.GetUtcOffset(date).Hours.ToString("00");
  var offsetMinutes = TimeZoneInfo.Local.GetUtcOffset(date).Minutes.ToString("00");
  Console.Write(string.Concat(strDate, offsetHours, offsetMinutes));

只是为了确保我理解正确:您正在显示UTC日期和时间,然后提供偏移量,以便读者可以自己进行计算吗?(例如,示例显示当地时间14:20:08。) - Jeff Sternal
没错。只是想知道是否有更简洁的方法来获取字符串。 - Mike
7个回答

11

这个怎么样:

.NET 4

 var utcOffset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now);
 Console.WriteLine(DateTime.UtcNow.ToString("yyyyMMddHHmmss") + ((utcOffset < TimeSpan.Zero) ? "-" : "+") + utcOffset.ToString("hhmm"));

.NET 3.5

 var utcAlmostFormat = DateTime.UtcNow.ToString("yyyyMMddHHmmss") + TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now);
 var utcFormat = System.Text.RegularExpressions.Regex.Replace(utcAlmostFormat, @"(\d\d):(\d\d):(\d\d)",@"$1$2");
 Console.WriteLine(utcFormat);

加油钢人(来自Strip区的一个人)


1
TimeSpan的ToString在3.5中没有格式重载 :( - Mike
@Mike - 哎呀,好的,我会使用你提供的方法或者在utcOffset.ToString()版本上使用substring。 - SwDevMan81
@Mike - 我添加了另一个版本,应该在3.5上可以运行,只是使用正则表达式格式化输出。 - SwDevMan81
1
第一个例子是错误的。你写成了ToString("hhss")。应该写成ToString("hhmm")。 - Matt Johnson-Pint

3

以下是一些扩展方法,可适用于.Net 3.5和.Net 4.0,并且可以非常直接地完成您所要求的操作:

public static string ToStringWithOffset(this DateTime dt)
{
  return new DateTimeOffset(dt).ToStringWithOffset();
}

public static string ToStringWithOffset(this DateTime dt, TimeSpan offset)
{
  return new DateTimeOffset(dt, offset).ToStringWithOffset();
}

public static string ToStringWithOffset(this DateTimeOffset dt)
{
  string sign = dt.Offset < TimeSpan.Zero ? "-" : "+";
  int hours = Math.Abs(dt.Offset.Hours);
  int minutes = Math.Abs(dt.Offset.Minutes);

  return string.Format("{0:yyyyMMddHHmmss}{1}{2:00}{3:00}", dt, sign, hours, minutes);
}

您现在可以在任何DateTime或DateTimeOffset上调用它们。例如:
string s = DateTime.Now.ToStringWithOffset();

或者

string s = DateTimeTimeOffset.Now.ToStringWithOffset();

或者

TimeSpan offset = TimeZoneInfo.Local.GetUtcOffset(someDate);
string s = someArbitraryTime.ToStringWithOffset(offset);

或者以其他方式,你可以想到很多种方法。

3
如果您有一个DateTimeOffset,那么自定义格式说明符zzz将输出时区偏移量,尽管使用更标准的"+HH:mm"格式。如果不想要冒号,可以使用字符串替换来解决问题。
Debug.WriteLine(DateTimeOffset.Now.ToString("yyyyMMddHHmmsszzz").Replace(":", ""));
// Result: "20110202153631-0500"

这不会产生世界协调时间(UTC)。 - SwDevMan81
3
指定时间和UTC偏移量的标准方式是使用本地时间和与UTC的偏移量。如果您使用UTC时间,并且未应用于时间的本地偏移量,则会导致错误,因为有人会假设它是按照标准方式完成的。 - David Yaw
我同意,只是给楼主想要的东西 :) - SwDevMan81
我将仔细检查以确保格式要求正确,因为这是有意义的。 - Mike

2
我们发现 DateTimeOffset.ToString("o") 最适合这种情况。例如:
DateTime.UtcNow.UtcToDateTimeOffset(User.GetTimeZone()).ToString("o");

如果您需要从 DateTime 进行转换,请使用类似的帮助方法:
    /// <summary>Converts from a UTC DateTime to the user's local DateTime</summary>
    /// <param name="utcDateTime">UTC DateTime</param>
    /// <param name="timeZoneInfo">The time zone info.</param>
    /// <returns>The DateTime in the user's time zone</returns>
    public static DateTimeOffset UtcToDateTimeOffset(this DateTime utcDateTime, TimeZoneInfo timeZoneInfo = null)
    {
        if (utcDateTime.Kind != DateTimeKind.Utc)
        {
            throw new InvalidTimeZoneException("Converting UTC to Local TimeZone, but was not UTC.");
        }

        DateTimeOffset dto = new DateTimeOffset(utcDateTime, TimeSpan.Zero);

        return timeZoneInfo.IsNotNull() ? dto.ToOffset(timeZoneInfo.GetUtcOffset(dto)) : dto;
    }

1
你可以使用一个 DateTime 标准格式 中的其中之一,或者创建一个 自定义格式
// Round-trip date/time pattern: "O", "o"
DateTime.Now.ToString("o") // "2018-01-15T11:00:50.5604578-05:00"
DateTime.UtcNow.ToString("o") // "2018-01-15T16:00:50.5604578Z"

// Universal sortable date/time pattern: "u"
DateTime.Now.ToString("u") // "2018-01-15 16:00:50.5604578Z"
DateTime.UtcNow.ToString("u") // "2018-01-15 16:00:50.5604578Z"

// Custom format
DateTime.Now.ToString("yyyyMMddHHmmssK") // "20180115160050-05:00"
DateTime.UtcNow.ToString("yyyyMMddHHmmssK") // "20180115160050Z"

0

尝试使用

var date = DateTimeOffset.Now;
var timestamp = $"{date:yyyy-MM-dd'T'HH:mm:ss.fff}{date.Offset.Ticks:+;-;}{date.Offset:hhmm}";

...或者类似这样的东西。


应该是{date.Offset:hh\:mm}。 - Alexey

-1

我认为有很多方法,比如:

  var offset = TimeZoneInfo.Local.BaseUtcOffset;
  string result = DateTime.UtcNow.ToString("yyyyMMddHHmmss") + offset.Hours.ToString("00") + offset.Minutes.ToString("00");

我认为您不想在此处使用“-”,因为这会意味着UTC偏移始终为负。 - SwDevMan81
-1:它是当前时区的偏移量,无论是否使用夏令时。目前在巴黎,我们处于UTC+2,但这段代码显示了1小时的偏移量。 - CharlesB

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接