Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/ServiceStack.Text/Common/DateTimeSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public static DateTime ParseShortestXsdDateTime(string dateTimeStr)

public static string ToDateTimeString(DateTime dateTime)
{
return TimeZoneInfo.ConvertTimeToUtc(dateTime).ToString(XsdDateTimeFormat);
return dateTime.ToStableUniversalTime().ToString(XsdDateTimeFormat);
}

public static DateTime ParseDateTime(string dateTimeStr)
Expand All @@ -66,7 +66,7 @@ public static DateTime ParseDateTime(string dateTimeStr)

public static string ToXsdDateTimeString(DateTime dateTime)
{
return XmlConvert.ToString(TimeZoneInfo.ConvertTimeToUtc(dateTime), XmlDateTimeSerializationMode.Utc);
return XmlConvert.ToString(dateTime.ToStableUniversalTime(), XmlDateTimeSerializationMode.Utc);
}

public static DateTime ParseXsdDateTime(string dateTimeStr)
Expand All @@ -82,7 +82,7 @@ public static string ToShortestXsdDateTimeString(DateTime dateTime)
return dateTime.ToString(ShortDateTimeFormat);

if (timeOfDay.Milliseconds == 0)
return TimeZoneInfo.ConvertTimeToUtc(dateTime).ToString(XsdDateTimeFormatSeconds);
return dateTime.ToStableUniversalTime().ToString(XsdDateTimeFormatSeconds);

return ToXsdDateTimeString(dateTime);
}
Expand Down
18 changes: 15 additions & 3 deletions src/ServiceStack.Text/DateTimeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public static class DateTimeExtensions

public static long ToUnixTime(this DateTime dateTime)
{
return (TimeZoneInfo.ConvertTimeToUtc(dateTime).Ticks - UnixEpoch) / TimeSpan.TicksPerSecond;
return (dateTime.ToStableUniversalTime().Ticks - UnixEpoch) / TimeSpan.TicksPerSecond;
}

public static DateTime FromUnixTime(this double unixTime)
Expand All @@ -36,7 +36,7 @@ public static DateTime FromUnixTime(this double unixTime)

public static long ToUnixTimeMs(this DateTime dateTime)
{
return (TimeZoneInfo.ConvertTimeToUtc(dateTime).Ticks - UnixEpoch) / TimeSpan.TicksPerMillisecond;
return (dateTime.ToStableUniversalTime().Ticks - UnixEpoch) / TimeSpan.TicksPerMillisecond;
}

public static DateTime FromUnixTimeMs(this double msSince1970)
Expand Down Expand Up @@ -99,7 +99,7 @@ public static DateTime FromShortestXsdDateTimeString(this string xsdDateTime)

public static bool IsEqualToTheSecond(this DateTime dateTime, DateTime otherDateTime)
{
return TimeZoneInfo.ConvertTimeToUtc(dateTime).RoundToSecond().Equals(TimeZoneInfo.ConvertTimeToUtc(otherDateTime).RoundToSecond());
return dateTime.ToStableUniversalTime().RoundToSecond().Equals(otherDateTime.ToStableUniversalTime().RoundToSecond());
}

public static string ToTimeOffsetString(this TimeSpan offset, bool includeColon = false)
Expand All @@ -120,5 +120,17 @@ public static TimeSpan FromTimeOffsetString(this string offsetString)

return TimeSpan.Parse(offsetString);
}

public static DateTime ToStableUniversalTime(this DateTime dateTime)
{
#if SILVERLIGHT
// Silverlight 3, 4 and 5 all work ok with DateTime.ToUniversalTime, but have no TimeZoneInfo.ConverTimeToUtc implementation.
return dateTime.ToUniversalTime();
#else
// .Net 2.0 - 3.5 has an issue with DateTime.ToUniversalTime, but works ok with TimeZoneInfo.ConvertTimeToUtc.
// .Net 4.0+ does this under the hood anyway.
return TimeZoneInfo.ConvertTimeToUtc(dateTime);
#endif
}
}
}
14 changes: 7 additions & 7 deletions tests/ServiceStack.Text.Tests/Utils/DateTimeSerializerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@ public void ToShortestXsdDateTimeString_works()
const string shortDateString = "1979-05-09";

var shortDateTime = new DateTime(1979, 5, 9, 0, 0, 1, DateTimeKind.Utc);
var shortDateTimeString = shortDateTime.Equals(TimeZoneInfo.ConvertTimeToUtc(shortDateTime))
var shortDateTimeString = shortDateTime.Equals(shortDateTime.ToStableUniversalTime())
? "1979-05-09T00:00:01Z"
: "1979-05-08T23:00:01Z";

var longDateTime = new DateTime(1979, 5, 9, 0, 0, 0, 1, DateTimeKind.Utc);
var longDateTimeString = longDateTime.Equals(TimeZoneInfo.ConvertTimeToUtc(longDateTime))
var longDateTimeString = longDateTime.Equals(longDateTime.ToStableUniversalTime())
? "1979-05-09T00:00:00.001Z"
: "1979-05-08T23:00:00.001Z";

Expand All @@ -58,7 +58,7 @@ public void ToShortestXsdDateTimeString_works()
public void Utc_Local_Equals()
{
var now = DateTime.Now;
var utcNow = TimeZoneInfo.ConvertTimeToUtc(now);
var utcNow = now.ToStableUniversalTime();

Assert.That(now.Ticks, Is.EqualTo(utcNow.Ticks), "Ticks are different");
Assert.That(now, Is.EqualTo(utcNow), "DateTimes are different");
Expand Down Expand Up @@ -122,7 +122,7 @@ public void AssertDateIsEqual(int whichDate)

//Don't test short dates without time to UTC as you lose precision
var shortDateStr = dateTime.ToString(DateTimeSerializer.ShortDateTimeFormat);
var shortDateTimeStr = TimeZoneInfo.ConvertTimeToUtc(dateTime).ToString(DateTimeSerializer.XsdDateTimeFormatSeconds);
var shortDateTimeStr = dateTime.ToStableUniversalTime().ToString(DateTimeSerializer.XsdDateTimeFormatSeconds);
var longDateTimeStr = DateTimeSerializer.ToXsdDateTimeString(dateTime);
var shortestDateStr = DateTimeSerializer.ToShortestXsdDateTimeString(dateTime);

Expand All @@ -135,14 +135,14 @@ public void AssertDateIsEqual(int whichDate)

Assert.That(shortDate, Is.EqualTo(dateTime.Date));

var shortDateTimeUtc = TimeZoneInfo.ConvertTimeToUtc(shortDateTime);
var shortDateTimeUtc = shortDateTime.ToStableUniversalTime();
Assert.That(shortDateTimeUtc, Is.EqualTo(
new DateTime(
shortDateTimeUtc.Year, shortDateTimeUtc.Month, shortDateTimeUtc.Day,
shortDateTimeUtc.Hour, shortDateTimeUtc.Minute, shortDateTimeUtc.Second,
shortDateTimeUtc.Millisecond, DateTimeKind.Utc)));

Assert.That(TimeZoneInfo.ConvertTimeToUtc(longDateTime), Is.EqualTo(TimeZoneInfo.ConvertTimeToUtc(dateTime)));
Assert.That(longDateTime.ToStableUniversalTime(), Is.EqualTo(dateTime.ToStableUniversalTime()));

var toDateTime = DateTimeSerializer.ParseShortestXsdDateTime(shortestDateStr);
AssertDatesAreEqual(toDateTime, dateTime, "shortestDate");
Expand All @@ -158,7 +158,7 @@ public void AssertDateIsEqual(int whichDate)

private void AssertDatesAreEqual(DateTime toDateTime, DateTime dateTime, string which)
{
Assert.That(TimeZoneInfo.ConvertTimeToUtc(toDateTime).RoundToMs(), Is.EqualTo(TimeZoneInfo.ConvertTimeToUtc(dateTime).RoundToMs()), which);
Assert.That(toDateTime.ToStableUniversalTime().RoundToMs(), Is.EqualTo(dateTime.ToStableUniversalTime().RoundToMs()), which);
}
}
}