mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Made time zone conversion more rubust.
This commit is contained in:
@@ -10,6 +10,7 @@ using Autofac;
|
||||
using NUnit.Framework;
|
||||
using Orchard.Localization.Models;
|
||||
using Orchard.Localization.Services;
|
||||
using Orchard.Services;
|
||||
|
||||
namespace Orchard.Tests.Localization {
|
||||
|
||||
@@ -25,10 +26,10 @@ namespace Orchard.Tests.Localization {
|
||||
[Description("Date component is decremented by one day when converting to time zone with negative offset greater than time component.")]
|
||||
public void ConvertToSiteTimeZoneTest01() {
|
||||
var timeZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
|
||||
Assert.That(timeZone.BaseUtcOffset, Is.LessThan(TimeSpan.FromHours(-3)));
|
||||
var container = TestHelpers.InitializeContainer(null, null, timeZone);
|
||||
var target = container.Resolve<IDateLocalizationServices>();
|
||||
var dateTimeUtc = new DateTime(1998, 1, 15, 3, 0, 0, DateTimeKind.Utc);
|
||||
Assert.That(timeZone.GetUtcOffset(dateTimeUtc), Is.LessThan(TimeSpan.FromHours(-3)));
|
||||
var target = container.Resolve<IDateLocalizationServices>();
|
||||
var result = target.ConvertToSiteTimeZone(dateTimeUtc);
|
||||
Assert.AreEqual(14, result.Day);
|
||||
}
|
||||
@@ -37,10 +38,10 @@ namespace Orchard.Tests.Localization {
|
||||
[Description("Date component is incremented by one day when converting to time zone with positive offset greater than 24 hours minus time component.")]
|
||||
public void ConvertToSiteTimeZoneTest02() {
|
||||
var timeZone = TimeZoneInfo.FindSystemTimeZoneById("India Standard Time");
|
||||
Assert.That(timeZone.BaseUtcOffset, Is.GreaterThan(TimeSpan.FromHours(3)));
|
||||
var container = TestHelpers.InitializeContainer(null, null, timeZone);
|
||||
var target = container.Resolve<IDateLocalizationServices>();
|
||||
var dateTimeUtc = new DateTime(1998, 1, 15, 21, 0, 0, DateTimeKind.Utc);
|
||||
Assert.That(timeZone.GetUtcOffset(dateTimeUtc), Is.GreaterThan(TimeSpan.FromHours(3)));
|
||||
var target = container.Resolve<IDateLocalizationServices>();
|
||||
var result = target.ConvertToSiteTimeZone(dateTimeUtc);
|
||||
Assert.AreEqual(16, result.Day);
|
||||
}
|
||||
@@ -49,10 +50,10 @@ namespace Orchard.Tests.Localization {
|
||||
[Description("DateTime which is DateTimeKind.Utc is converted to DateTimeKind.Local with offset when target time zone is not UTC.")]
|
||||
public void ConvertToSiteTimeZoneTest03() {
|
||||
var timeZone = TimeZoneInfo.FindSystemTimeZoneById("Central European Standard Time");
|
||||
Assert.That(timeZone.BaseUtcOffset, Is.Not.EqualTo(TimeSpan.Zero));
|
||||
var container = TestHelpers.InitializeContainer(null, null, timeZone);
|
||||
var target = container.Resolve<IDateLocalizationServices>();
|
||||
var dateTimeUtc = new DateTime(1998, 1, 15, 3, 0, 0, DateTimeKind.Utc);
|
||||
Assert.That(timeZone.GetUtcOffset(dateTimeUtc), Is.Not.EqualTo(TimeSpan.Zero));
|
||||
var target = container.Resolve<IDateLocalizationServices>();
|
||||
var result = target.ConvertToSiteTimeZone(dateTimeUtc);
|
||||
Assert.AreEqual(DateTimeKind.Local, result.Kind);
|
||||
Assert.AreEqual(dateTimeUtc.Hour + timeZone.BaseUtcOffset.Hours, result.Hour);
|
||||
@@ -62,10 +63,10 @@ namespace Orchard.Tests.Localization {
|
||||
[Description("DateTime which is DateTimeKind.Utc is not converted when target time zone is UTC.")]
|
||||
public void ConvertToSiteTimeZoneTest04() {
|
||||
var timeZone = TimeZoneInfo.FindSystemTimeZoneById("UTC");
|
||||
Assert.That(timeZone.BaseUtcOffset, Is.EqualTo(TimeSpan.Zero));
|
||||
var container = TestHelpers.InitializeContainer(null, null, timeZone);
|
||||
var target = container.Resolve<IDateLocalizationServices>();
|
||||
var dateTimeUtc = new DateTime(1998, 1, 15, 3, 0, 0, DateTimeKind.Utc);
|
||||
Assert.That(timeZone.GetUtcOffset(dateTimeUtc), Is.EqualTo(TimeSpan.Zero));
|
||||
var target = container.Resolve<IDateLocalizationServices>();
|
||||
var result = target.ConvertToSiteTimeZone(dateTimeUtc);
|
||||
Assert.AreEqual(DateTimeKind.Utc, result.Kind);
|
||||
Assert.AreEqual(dateTimeUtc, result);
|
||||
@@ -75,10 +76,10 @@ namespace Orchard.Tests.Localization {
|
||||
[Description("DateTime which is DateTimeKind.Unspecified is converted to DateTimeKind.Local with offset when target time zone is not UTC.")]
|
||||
public void ConvertToSiteTimeZoneTest05() {
|
||||
var timeZone = TimeZoneInfo.FindSystemTimeZoneById("Central European Standard Time");
|
||||
Assert.That(timeZone.BaseUtcOffset, Is.Not.EqualTo(TimeSpan.Zero));
|
||||
var container = TestHelpers.InitializeContainer(null, null, timeZone);
|
||||
var target = container.Resolve<IDateLocalizationServices>();
|
||||
var dateTimeUtc = new DateTime(1998, 1, 15, 3, 0, 0, DateTimeKind.Unspecified);
|
||||
Assert.That(timeZone.GetUtcOffset(dateTimeUtc), Is.Not.EqualTo(TimeSpan.Zero));
|
||||
var target = container.Resolve<IDateLocalizationServices>();
|
||||
var result = target.ConvertToSiteTimeZone(dateTimeUtc);
|
||||
Assert.AreEqual(DateTimeKind.Local, result.Kind);
|
||||
Assert.AreEqual(dateTimeUtc.Hour + timeZone.BaseUtcOffset.Hours, result.Hour);
|
||||
@@ -88,10 +89,10 @@ namespace Orchard.Tests.Localization {
|
||||
[Description("DateTime which is DateTimeKind.Unspecified is converted to DateTimeKind.Utc with no offset when target time zone is UTC.")]
|
||||
public void ConvertToSiteTimeZoneTest06() {
|
||||
var timeZone = TimeZoneInfo.FindSystemTimeZoneById("UTC");
|
||||
Assert.That(timeZone.BaseUtcOffset, Is.EqualTo(TimeSpan.Zero));
|
||||
var container = TestHelpers.InitializeContainer(null, null, timeZone);
|
||||
var target = container.Resolve<IDateLocalizationServices>();
|
||||
var dateTimeUtc = new DateTime(1998, 1, 15, 3, 0, 0, DateTimeKind.Unspecified);
|
||||
Assert.That(timeZone.GetUtcOffset(dateTimeUtc), Is.EqualTo(TimeSpan.Zero));
|
||||
var target = container.Resolve<IDateLocalizationServices>();
|
||||
var result = target.ConvertToSiteTimeZone(dateTimeUtc);
|
||||
Assert.AreEqual(DateTimeKind.Utc, result.Kind);
|
||||
Assert.AreEqual(dateTimeUtc, result);
|
||||
@@ -101,10 +102,10 @@ namespace Orchard.Tests.Localization {
|
||||
[Description("DateTime which is already DateTimeKind.Local is never converted.")]
|
||||
public void ConvertToSiteTimeZoneTest07() {
|
||||
var timeZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
|
||||
Assert.That(timeZone.BaseUtcOffset, Is.Not.EqualTo(TimeSpan.Zero));
|
||||
var container = TestHelpers.InitializeContainer(null, null, timeZone);
|
||||
var target = container.Resolve<IDateLocalizationServices>();
|
||||
var dateTimeUtc = new DateTime(1998, 1, 15, 3, 0, 0, DateTimeKind.Local);
|
||||
Assert.That(timeZone.GetUtcOffset(dateTimeUtc), Is.Not.EqualTo(TimeSpan.Zero));
|
||||
var target = container.Resolve<IDateLocalizationServices>();
|
||||
var result = target.ConvertToSiteTimeZone(dateTimeUtc);
|
||||
Assert.AreEqual(DateTimeKind.Local, result.Kind);
|
||||
Assert.AreEqual(dateTimeUtc, result);
|
||||
@@ -117,10 +118,10 @@ namespace Orchard.Tests.Localization {
|
||||
if (timeZone == TimeZoneInfo.Local) {
|
||||
timeZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
|
||||
}
|
||||
Assert.That(timeZone.BaseUtcOffset, Is.Not.EqualTo(TimeSpan.Zero));
|
||||
var container = TestHelpers.InitializeContainer(null, null, timeZone);
|
||||
var target = container.Resolve<IDateLocalizationServices>();
|
||||
var dateTimeUtc = new DateTime(1998, 1, 15, 3, 0, 0, DateTimeKind.Utc);
|
||||
Assert.That(timeZone.GetUtcOffset(dateTimeUtc), Is.Not.EqualTo(TimeSpan.Zero));
|
||||
var target = container.Resolve<IDateLocalizationServices>();
|
||||
var result = target.ConvertToSiteTimeZone(dateTimeUtc);
|
||||
Assert.AreEqual(DateTimeKind.Local, result.Kind);
|
||||
}
|
||||
@@ -129,10 +130,10 @@ namespace Orchard.Tests.Localization {
|
||||
[Description("Date component is incremented by one day when converting from time zone with negative offset greater than 24 hours minus time component.")]
|
||||
public void ConvertFromSiteTimeZoneTest01() {
|
||||
var timeZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
|
||||
Assert.That(timeZone.BaseUtcOffset, Is.LessThan(TimeSpan.FromHours(-3)));
|
||||
var container = TestHelpers.InitializeContainer(null, null, timeZone);
|
||||
var target = container.Resolve<IDateLocalizationServices>();
|
||||
var dateTimeLocal = new DateTime(1998, 1, 15, 21, 0, 0, DateTimeKind.Local);
|
||||
Assert.That(timeZone.GetUtcOffset(dateTimeLocal), Is.LessThan(TimeSpan.FromHours(-3)));
|
||||
var target = container.Resolve<IDateLocalizationServices>();
|
||||
var result = target.ConvertFromSiteTimeZone(dateTimeLocal);
|
||||
Assert.AreEqual(16, result.Day);
|
||||
}
|
||||
@@ -141,10 +142,10 @@ namespace Orchard.Tests.Localization {
|
||||
[Description("Date component is decremented by one day when converting from time zone with positive offset greater than time component.")]
|
||||
public void ConvertFromSiteTimeZoneTest02() {
|
||||
var timeZone = TimeZoneInfo.FindSystemTimeZoneById("India Standard Time");
|
||||
Assert.That(timeZone.BaseUtcOffset, Is.GreaterThan(TimeSpan.FromHours(3)));
|
||||
var container = TestHelpers.InitializeContainer(null, null, timeZone);
|
||||
var target = container.Resolve<IDateLocalizationServices>();
|
||||
var dateTimeLocal = new DateTime(1998, 1, 15, 3, 0, 0, DateTimeKind.Local);
|
||||
Assert.That(timeZone.GetUtcOffset(dateTimeLocal), Is.GreaterThan(TimeSpan.FromHours(3)));
|
||||
var target = container.Resolve<IDateLocalizationServices>();
|
||||
var result = target.ConvertFromSiteTimeZone(dateTimeLocal);
|
||||
Assert.AreEqual(14, result.Day);
|
||||
}
|
||||
@@ -153,10 +154,10 @@ namespace Orchard.Tests.Localization {
|
||||
[Description("DateTime which is DateTimeKind.Local is converted to DateTimeKind.Utc with offset when target time zone is not UTC.")]
|
||||
public void ConvertFromSiteTimeZoneTest03() {
|
||||
var timeZone = TimeZoneInfo.FindSystemTimeZoneById("Central European Standard Time");
|
||||
Assert.That(timeZone.BaseUtcOffset, Is.Not.EqualTo(TimeSpan.Zero));
|
||||
var container = TestHelpers.InitializeContainer(null, null, timeZone);
|
||||
var target = container.Resolve<IDateLocalizationServices>();
|
||||
var dateTimeLocal = new DateTime(1998, 1, 15, 21, 0, 0, DateTimeKind.Local);
|
||||
Assert.That(timeZone.GetUtcOffset(dateTimeLocal), Is.Not.EqualTo(TimeSpan.Zero));
|
||||
var target = container.Resolve<IDateLocalizationServices>();
|
||||
var result = target.ConvertFromSiteTimeZone(dateTimeLocal);
|
||||
Assert.AreEqual(DateTimeKind.Utc, result.Kind);
|
||||
Assert.AreEqual(dateTimeLocal.Hour - timeZone.BaseUtcOffset.Hours, result.Hour);
|
||||
@@ -166,10 +167,10 @@ namespace Orchard.Tests.Localization {
|
||||
[Description("DateTime which is DateTimeKind.Local is converted to DateTimeKind.Utc with no offset when target time zone is UTC.")]
|
||||
public void ConvertFromSiteTimeZoneTest04() {
|
||||
var timeZone = TimeZoneInfo.FindSystemTimeZoneById("UTC");
|
||||
Assert.That(timeZone.BaseUtcOffset, Is.EqualTo(TimeSpan.Zero));
|
||||
var container = TestHelpers.InitializeContainer(null, null, timeZone);
|
||||
var target = container.Resolve<IDateLocalizationServices>();
|
||||
var dateTimeLocal = new DateTime(1998, 1, 15, 21, 0, 0, DateTimeKind.Local);
|
||||
Assert.That(timeZone.GetUtcOffset(dateTimeLocal), Is.EqualTo(TimeSpan.Zero));
|
||||
var target = container.Resolve<IDateLocalizationServices>();
|
||||
var result = target.ConvertFromSiteTimeZone(dateTimeLocal);
|
||||
Assert.AreEqual(DateTimeKind.Utc, result.Kind);
|
||||
Assert.AreEqual(dateTimeLocal.Hour, result.Hour);
|
||||
@@ -180,10 +181,10 @@ namespace Orchard.Tests.Localization {
|
||||
[Description("DateTime which is DateTimeKind.Unspecified is converted to DateTimeKind.Utc with offset when target time zone is not UTC.")]
|
||||
public void ConvertFromSiteTimeZoneTest05() {
|
||||
var timeZone = TimeZoneInfo.FindSystemTimeZoneById("Central European Standard Time");
|
||||
Assert.That(timeZone.BaseUtcOffset, Is.Not.EqualTo(TimeSpan.Zero));
|
||||
var container = TestHelpers.InitializeContainer(null, null, timeZone);
|
||||
var target = container.Resolve<IDateLocalizationServices>();
|
||||
var dateTimeLocal = new DateTime(1998, 1, 15, 21, 0, 0, DateTimeKind.Unspecified);
|
||||
Assert.That(timeZone.GetUtcOffset(dateTimeLocal), Is.Not.EqualTo(TimeSpan.Zero));
|
||||
var target = container.Resolve<IDateLocalizationServices>();
|
||||
var result = target.ConvertFromSiteTimeZone(dateTimeLocal);
|
||||
Assert.AreEqual(DateTimeKind.Utc, result.Kind);
|
||||
Assert.AreEqual(dateTimeLocal.Hour - timeZone.BaseUtcOffset.Hours, result.Hour);
|
||||
@@ -193,10 +194,10 @@ namespace Orchard.Tests.Localization {
|
||||
[Description("DateTime which is DateTimeKind.Unspecified is converted to DateTimeKind.Utc with no offset when target time zone is UTC.")]
|
||||
public void ConvertFromSiteTimeZoneTest06() {
|
||||
var timeZone = TimeZoneInfo.FindSystemTimeZoneById("UTC");
|
||||
Assert.That(timeZone.BaseUtcOffset, Is.EqualTo(TimeSpan.Zero));
|
||||
var container = TestHelpers.InitializeContainer(null, null, timeZone);
|
||||
var target = container.Resolve<IDateLocalizationServices>();
|
||||
var dateTimeLocal = new DateTime(1998, 1, 15, 21, 0, 0, DateTimeKind.Unspecified);
|
||||
Assert.That(timeZone.GetUtcOffset(dateTimeLocal), Is.EqualTo(TimeSpan.Zero));
|
||||
var target = container.Resolve<IDateLocalizationServices>();
|
||||
var result = target.ConvertFromSiteTimeZone(dateTimeLocal);
|
||||
Assert.AreEqual(DateTimeKind.Utc, result.Kind);
|
||||
Assert.AreEqual(dateTimeLocal.Hour, result.Hour);
|
||||
@@ -207,13 +208,37 @@ namespace Orchard.Tests.Localization {
|
||||
[Description("DateTime which is already DateTimeKind.Utc is never converted.")]
|
||||
public void ConvertFromSiteTimeZoneTest07() {
|
||||
var timeZone = TimeZoneInfo.FindSystemTimeZoneById("Central European Standard Time");
|
||||
Assert.That(timeZone.BaseUtcOffset, Is.Not.EqualTo(TimeSpan.Zero));
|
||||
var container = TestHelpers.InitializeContainer(null, null, timeZone);
|
||||
var target = container.Resolve<IDateLocalizationServices>();
|
||||
var dateTimeLocal = new DateTime(1998, 1, 15, 21, 0, 0, DateTimeKind.Utc);
|
||||
Assert.That(timeZone.GetUtcOffset(dateTimeLocal), Is.Not.EqualTo(TimeSpan.Zero));
|
||||
var target = container.Resolve<IDateLocalizationServices>();
|
||||
var result = target.ConvertFromSiteTimeZone(dateTimeLocal);
|
||||
Assert.AreEqual(DateTimeKind.Utc, result.Kind);
|
||||
Assert.AreEqual(dateTimeLocal, result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Description("Converting to Gregorian calendar yields a DateTimeParts instance equivalent to the original DateTime.")]
|
||||
public void ConvertToSiteCalendarTest01() {
|
||||
Assert.Inconclusive();
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Description("Converting to non-Gregorian calendar yields a DateTimeParts instance with correct values.")]
|
||||
public void ConvertToSiteCalendarTest02() {
|
||||
Assert.Inconclusive();
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Description("Converting from Gregorian calendar yields a DateTime equivalent to the original DateTimeParts instance.")]
|
||||
public void ConvertFromSiteCalendarTest01() {
|
||||
Assert.Inconclusive();
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Description("Converting from non-Gregorian calendar yields a DateTime with correct values.")]
|
||||
public void ConvertFromSiteCalendarTest02() {
|
||||
Assert.Inconclusive();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -29,6 +29,11 @@ namespace Orchard.Localization.Services {
|
||||
}
|
||||
|
||||
public virtual DateTime ConvertToSiteTimeZone(DateTime dateUtc) {
|
||||
// Some trickery is necessary for correct handling of DateTimeKind values
|
||||
// of both input and output dates, because the TimeZoneInfo class' internal
|
||||
// handling of this is tightly coupled to the configured time zone of
|
||||
// the local computer, which can differ from the configured time zone of
|
||||
// the Orchard site.
|
||||
if (dateUtc.Kind == DateTimeKind.Local) {
|
||||
return dateUtc;
|
||||
}
|
||||
@@ -38,15 +43,21 @@ namespace Orchard.Localization.Services {
|
||||
}
|
||||
return dateUtc;
|
||||
}
|
||||
var dateLocal = dateUtc + CurrentTimeZone.BaseUtcOffset;
|
||||
var dateLocal = TimeZoneInfo.ConvertTimeFromUtc(dateUtc, CurrentTimeZone);
|
||||
return new DateTime(dateLocal.Ticks, DateTimeKind.Local);
|
||||
}
|
||||
|
||||
public virtual DateTime ConvertFromSiteTimeZone(DateTime dateLocal) {
|
||||
// Some trickery is necessary for correct handling of DateTimeKind values
|
||||
// of both input and output dates, because the TimeZoneInfo class' internal
|
||||
// handling of this is tightly coupled to the configured time zone of
|
||||
// the local computer, which can differ from the configured time zone of
|
||||
// the Orchard site.
|
||||
if (dateLocal.Kind == DateTimeKind.Utc) {
|
||||
return dateLocal;
|
||||
}
|
||||
var dateUtc = dateLocal - CurrentTimeZone.BaseUtcOffset;
|
||||
}
|
||||
var dateUnspecified = new DateTime(dateLocal.Ticks, DateTimeKind.Unspecified);
|
||||
var dateUtc = TimeZoneInfo.ConvertTimeToUtc(dateUnspecified, CurrentTimeZone);
|
||||
return new DateTime(dateUtc.Ticks, DateTimeKind.Utc);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user