提交 5a853002 编写于 作者: M Maxim Lipnin 提交者: Scott Ferguson

Port 13553 "Fix transition offset logic" to master

上级 ad6f94d8
......@@ -805,7 +805,7 @@ namespace System
return GetUtcOffset (dateTimeOffset.UtcDateTime, out isDST);
}
private TimeSpan GetUtcOffset (DateTime dateTime, out bool isDST)
private TimeSpan GetUtcOffset (DateTime dateTime, out bool isDST, bool forOffset = false)
{
isDST = false;
......@@ -817,7 +817,7 @@ namespace System
tz = TimeZoneInfo.Local;
bool isTzDst;
var tzOffset = GetUtcOffsetHelper (dateTime, tz, out isTzDst);
var tzOffset = GetUtcOffsetHelper (dateTime, tz, out isTzDst, forOffset);
if (tz == this) {
isDST = isTzDst;
......@@ -828,11 +828,11 @@ namespace System
if (!TryAddTicks (dateTime, -tzOffset.Ticks, out utcDateTime, DateTimeKind.Utc))
return BaseUtcOffset;
return GetUtcOffsetHelper (utcDateTime, this, out isDST);
return GetUtcOffsetHelper (utcDateTime, this, out isDST, forOffset);
}
// This is an helper method used by the method above, do not use this on its own.
private static TimeSpan GetUtcOffsetHelper (DateTime dateTime, TimeZoneInfo tz, out bool isDST)
private static TimeSpan GetUtcOffsetHelper (DateTime dateTime, TimeZoneInfo tz, out bool isDST, bool forOffset = false)
{
if (dateTime.Kind == DateTimeKind.Local && tz != TimeZoneInfo.Local)
throw new Exception ();
......@@ -843,7 +843,7 @@ namespace System
return TimeSpan.Zero;
TimeSpan offset;
if (tz.TryGetTransitionOffset(dateTime, out offset, out isDST))
if (tz.TryGetTransitionOffset(dateTime, out offset, out isDST, forOffset))
return offset;
if (dateTime.Kind == DateTimeKind.Utc) {
......@@ -870,10 +870,12 @@ namespace System
if (tzRule != null && tz.IsInDST (tzRule, dateTime)) {
// Replicate what .NET does when given a time which falls into the hour which is lost when
// DST starts. isDST should always be true but the offset should be BaseUtcOffset without the
// DST starts. isDST should be false and the offset should be BaseUtcOffset without the
// DST delta while in that hour.
isDST = true;
if (forOffset)
isDST = true;
if (tz.IsInDST (tzRule, dstUtcDateTime)) {
isDST = true;
return tz.BaseUtcOffset + tzRule.DaylightDelta;
} else {
return tz.BaseUtcOffset;
......@@ -982,7 +984,21 @@ namespace System
public bool IsDaylightSavingTime (DateTimeOffset dateTimeOffset)
{
return IsDaylightSavingTime (dateTimeOffset.DateTime);
var dateTime = dateTimeOffset.DateTime;
if (dateTime.Kind == DateTimeKind.Local && IsInvalidTime (dateTime))
throw new ArgumentException ("dateTime is invalid and Kind is Local");
if (this == TimeZoneInfo.Utc)
return false;
if (!SupportsDaylightSavingTime)
return false;
bool isDst;
GetUtcOffset (dateTime, out isDst, true);
return isDst;
}
internal DaylightTime GetDaylightChanges (int year)
......@@ -1219,7 +1235,7 @@ namespace System
return null;
}
private bool TryGetTransitionOffset (DateTime dateTime, out TimeSpan offset,out bool isDst)
private bool TryGetTransitionOffset (DateTime dateTime, out TimeSpan offset, out bool isDst, bool forOffset = false)
{
offset = BaseUtcOffset;
isDst = false;
......@@ -1240,13 +1256,22 @@ namespace System
return false;
}
AdjustmentRule current = GetApplicableRule(date);
AdjustmentRule current = GetApplicableRule (date);
if (current != null) {
DateTime tStart = TransitionPoint(current.DaylightTransitionStart, date.Year);
DateTime tEnd = TransitionPoint(current.DaylightTransitionEnd, date.Year);
DateTime tStart = TransitionPoint (current.DaylightTransitionStart, date.Year);
DateTime tEnd = TransitionPoint (current.DaylightTransitionEnd, date.Year);
TryAddTicks (tStart, -BaseUtcOffset.Ticks, out tStart, DateTimeKind.Utc);
TryAddTicks (tEnd, -BaseUtcOffset.Ticks, out tEnd, DateTimeKind.Utc);
if ((date >= tStart) && (date <= tEnd)) {
offset = baseUtcOffset + current.DaylightDelta;
isDst = true;
if (forOffset)
isDst = true;
offset = baseUtcOffset;
if (date >= new DateTime (tStart.Ticks + current.DaylightDelta.Ticks, DateTimeKind.Utc))
{
offset += current.DaylightDelta;
isDst = true;
}
return true;
}
}
......
......@@ -55,6 +55,8 @@ namespace MonoTests.System
return "GTB Standard Time";
case "US/Eastern":
return "Eastern Standard Time";
case "US/Central":
return "Central Standard Time";
case "US/Pacific":
return "Pacific Standard Time";
case "Australia/Sydney":
......@@ -760,13 +762,18 @@ namespace MonoTests.System
[Test]
public void TestAthensDST_InDSTDelta ()
{
// In .NET GetUtcOffset() returns the BaseUtcOffset for times within the hour
// lost when DST starts but IsDaylightSavingTime() returns true.
// In .NET/.Net Core GetUtcOffset() returns the BaseUtcOffset for times within the hour
// lost when DST starts and IsDaylightSavingTime() returns false for datetime and true for datetimeoffset
TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById (MapTimeZoneId ("Europe/Athens"));
var date = new DateTime (2014, 3, 30 , 3, 0, 0);
Assert.IsTrue (tzi.IsDaylightSavingTime (date));
var date = new DateTime (2014, 3, 30 , 2, 0, 0);
Assert.IsFalse (tzi.IsDaylightSavingTime (date));
Assert.AreEqual (new TimeSpan (2, 0, 0), tzi.GetUtcOffset (date));
Assert.IsFalse (tzi.IsDaylightSavingTime (new DateTimeOffset (date, tzi.GetUtcOffset (date))));
date = new DateTime (2014, 3, 30 , 3, 0, 0);
Assert.IsFalse (tzi.IsDaylightSavingTime (date));
Assert.AreEqual (new TimeSpan (2, 0, 0), tzi.GetUtcOffset (date));
Assert.IsTrue (tzi.IsDaylightSavingTime (new DateTimeOffset (date, tzi.GetUtcOffset (date))));
......@@ -842,6 +849,31 @@ namespace MonoTests.System
dateOffset = new DateTimeOffset (date, offset);
Assert.IsTrue (tzi.IsDaylightSavingTime (dateOffset));
}
// https://github.com/mono/mono/issues/9664
[Test]
public void Bug_9664 ()
{
TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById (MapTimeZoneId ("US/Central"));
var date = new DateTime (2019, 3, 9, 21, 0, 0);
Assert.IsFalse (tzi.IsDaylightSavingTime (date));
Assert.AreEqual (new TimeSpan (-6, 0, 0), tzi.GetUtcOffset (date));
tzi = TimeZoneInfo.FindSystemTimeZoneById (MapTimeZoneId ("US/Central"));
date = new DateTime (2019, 3, 10, 2, 0, 0);
Assert.IsFalse (tzi.IsDaylightSavingTime (date));
Assert.AreEqual (new TimeSpan (-6, 0, 0), tzi.GetUtcOffset (date));
tzi = TimeZoneInfo.FindSystemTimeZoneById (MapTimeZoneId ("US/Central"));
date = new DateTime (2019, 3, 10, 2, 30, 0);
Assert.IsFalse (tzi.IsDaylightSavingTime (date));
Assert.AreEqual (new TimeSpan (-6, 0, 0), tzi.GetUtcOffset (date));
tzi = TimeZoneInfo.FindSystemTimeZoneById (MapTimeZoneId ("US/Central"));
date = new DateTime (2019, 3, 10, 3, 0, 0);
Assert.IsTrue (tzi.IsDaylightSavingTime (date));
Assert.AreEqual (new TimeSpan (-5, 0, 0), tzi.GetUtcOffset (date));
}
}
[TestFixture]
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册