mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Added 15 unit tests to cover time zone conversion, and fixed a bug that the new tests revealed.
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
using NUnit.Framework;
|
||||
using Orchard.Localization.Models;
|
||||
|
||||
namespace Orchard.Framework.Tests.Localization {
|
||||
namespace Orchard.Tests.Localization {
|
||||
|
||||
[TestFixture]
|
||||
public class DateTimePartsTests {
|
||||
|
@@ -7,12 +7,11 @@ using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Autofac;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Orchard.Localization.Models;
|
||||
using Orchard.Localization.Services;
|
||||
|
||||
namespace Orchard.Framework.Tests.Localization {
|
||||
namespace Orchard.Tests.Localization {
|
||||
|
||||
[TestFixture]
|
||||
public class DefaultDateFormatterTests {
|
||||
@@ -36,7 +35,7 @@ namespace Orchard.Framework.Tests.Localization {
|
||||
|
||||
var allCultures = CultureInfo.GetCultures(CultureTypes.AllCultures);
|
||||
Parallel.ForEach(allCultures, options, culture => { // All cultures on the machine.
|
||||
var container = InitializeContainer(culture.Name, "GregorianCalendar", TimeZoneInfo.Utc);
|
||||
var container = TestHelpers.InitializeContainer(culture.Name, "GregorianCalendar", TimeZoneInfo.Utc);
|
||||
var formats = container.Resolve<IDateTimeFormatProvider>();
|
||||
var target = container.Resolve<IDateFormatter>();
|
||||
|
||||
@@ -85,7 +84,7 @@ namespace Orchard.Framework.Tests.Localization {
|
||||
|
||||
var allCultures = CultureInfo.GetCultures(CultureTypes.AllCultures);
|
||||
Parallel.ForEach(allCultures, options, culture => { // All cultures on the machine.
|
||||
var container = InitializeContainer(culture.Name, "GregorianCalendar", TimeZoneInfo.Utc);
|
||||
var container = TestHelpers.InitializeContainer(culture.Name, "GregorianCalendar", TimeZoneInfo.Utc);
|
||||
var formats = container.Resolve<IDateTimeFormatProvider>();
|
||||
var target = container.Resolve<IDateFormatter>();
|
||||
|
||||
@@ -135,7 +134,7 @@ namespace Orchard.Framework.Tests.Localization {
|
||||
var allCultures = CultureInfo.GetCultures(CultureTypes.AllCultures);
|
||||
Parallel.ForEach(allCultures, options, culture => { // All cultures on the machine.
|
||||
foreach (var timeZone in new[] { TimeZoneInfo.Utc, TimeZoneInfo.Local, TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time"), TimeZoneInfo.FindSystemTimeZoneById("Iran Standard Time") }) { // Enough time zones to get good coverage: UTC, local, one negative offset and one positive offset.
|
||||
var container = InitializeContainer(culture.Name, "GregorianCalendar", timeZone);
|
||||
var container = TestHelpers.InitializeContainer(culture.Name, "GregorianCalendar", timeZone);
|
||||
var formats = container.Resolve<IDateTimeFormatProvider>();
|
||||
var target = container.Resolve<IDateFormatter>();
|
||||
|
||||
@@ -192,7 +191,7 @@ namespace Orchard.Framework.Tests.Localization {
|
||||
[Description("Date/time parsing throws a FormatException for unparsable date/time strings.")]
|
||||
[ExpectedException(typeof(FormatException))]
|
||||
public void ParseDateTimeTest04() {
|
||||
var container = InitializeContainer("en-US", null, TimeZoneInfo.Utc);
|
||||
var container = TestHelpers.InitializeContainer("en-US", null, TimeZoneInfo.Utc);
|
||||
var target = container.Resolve<IDateFormatter>();
|
||||
target.ParseDateTime("BlaBlaBla");
|
||||
}
|
||||
@@ -211,7 +210,7 @@ namespace Orchard.Framework.Tests.Localization {
|
||||
|
||||
var allCultures = CultureInfo.GetCultures(CultureTypes.AllCultures);
|
||||
Parallel.ForEach(allCultures, options, culture => { // All cultures on the machine.
|
||||
var container = InitializeContainer(culture.Name, "GregorianCalendar", TimeZoneInfo.Utc);
|
||||
var container = TestHelpers.InitializeContainer(culture.Name, "GregorianCalendar", TimeZoneInfo.Utc);
|
||||
var formats = container.Resolve<IDateTimeFormatProvider>();
|
||||
var target = container.Resolve<IDateFormatter>();
|
||||
|
||||
@@ -250,7 +249,7 @@ namespace Orchard.Framework.Tests.Localization {
|
||||
[Description("Date parsing throws a FormatException for unparsable date strings.")]
|
||||
[ExpectedException(typeof(FormatException))]
|
||||
public void ParseDateTest02() {
|
||||
var container = InitializeContainer("en-US", null, TimeZoneInfo.Utc);
|
||||
var container = TestHelpers.InitializeContainer("en-US", null, TimeZoneInfo.Utc);
|
||||
var target = container.Resolve<IDateFormatter>();
|
||||
target.ParseDate("BlaBlaBla");
|
||||
}
|
||||
@@ -269,7 +268,7 @@ namespace Orchard.Framework.Tests.Localization {
|
||||
|
||||
var allCultures = CultureInfo.GetCultures(CultureTypes.AllCultures);
|
||||
Parallel.ForEach(allCultures, options, culture => { // All cultures on the machine.
|
||||
var container = InitializeContainer(culture.Name, null, TimeZoneInfo.Utc);
|
||||
var container = TestHelpers.InitializeContainer(culture.Name, null, TimeZoneInfo.Utc);
|
||||
var formats = container.Resolve<IDateTimeFormatProvider>();
|
||||
var target = container.Resolve<IDateFormatter>();
|
||||
|
||||
@@ -304,7 +303,7 @@ namespace Orchard.Framework.Tests.Localization {
|
||||
[Description("Time parsing throws a FormatException for unparsable time strings.")]
|
||||
[ExpectedException(typeof(FormatException))]
|
||||
public void ParseTimeTest02() {
|
||||
var container = InitializeContainer("en-US", null, TimeZoneInfo.Utc);
|
||||
var container = TestHelpers.InitializeContainer("en-US", null, TimeZoneInfo.Utc);
|
||||
var target = container.Resolve<IDateFormatter>();
|
||||
target.ParseTime("BlaBlaBla");
|
||||
}
|
||||
@@ -323,7 +322,7 @@ namespace Orchard.Framework.Tests.Localization {
|
||||
|
||||
var allCultures = CultureInfo.GetCultures(CultureTypes.AllCultures);
|
||||
Parallel.ForEach(allCultures, options, culture => { // All cultures on the machine.
|
||||
var container = InitializeContainer(culture.Name, "GregorianCalendar", TimeZoneInfo.Utc);
|
||||
var container = TestHelpers.InitializeContainer(culture.Name, "GregorianCalendar", TimeZoneInfo.Utc);
|
||||
var formats = container.Resolve<IDateTimeFormatProvider>();
|
||||
var target = container.Resolve<IDateFormatter>();
|
||||
|
||||
@@ -386,7 +385,7 @@ namespace Orchard.Framework.Tests.Localization {
|
||||
|
||||
var allCultures = CultureInfo.GetCultures(CultureTypes.AllCultures);
|
||||
Parallel.ForEach(allCultures, options, culture => { // All cultures on the machine.
|
||||
var container = InitializeContainer(culture.Name, "GregorianCalendar", TimeZoneInfo.Utc);
|
||||
var container = TestHelpers.InitializeContainer(culture.Name, "GregorianCalendar", TimeZoneInfo.Utc);
|
||||
var formats = container.Resolve<IDateTimeFormatProvider>();
|
||||
var target = container.Resolve<IDateFormatter>();
|
||||
|
||||
@@ -450,7 +449,7 @@ namespace Orchard.Framework.Tests.Localization {
|
||||
var allCultures = CultureInfo.GetCultures(CultureTypes.AllCultures);
|
||||
Parallel.ForEach(allCultures, options, culture => { // All cultures on the machine.
|
||||
foreach (var timeZone in new[] { TimeZoneInfo.Utc, TimeZoneInfo.Local, TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time"), TimeZoneInfo.FindSystemTimeZoneById("Iran Standard Time") }) { // Enough time zones to get good coverage: UTC, local, one negative offset and one positive offset.
|
||||
var container = InitializeContainer(culture.Name, "GregorianCalendar", timeZone);
|
||||
var container = TestHelpers.InitializeContainer(culture.Name, "GregorianCalendar", timeZone);
|
||||
var formats = container.Resolve<IDateTimeFormatProvider>();
|
||||
var target = container.Resolve<IDateFormatter>();
|
||||
|
||||
@@ -540,7 +539,7 @@ namespace Orchard.Framework.Tests.Localization {
|
||||
|
||||
var allCultures = CultureInfo.GetCultures(CultureTypes.AllCultures);
|
||||
Parallel.ForEach(allCultures, options, culture => { // All cultures on the machine.
|
||||
var container = InitializeContainer(culture.Name, "GregorianCalendar", TimeZoneInfo.Utc);
|
||||
var container = TestHelpers.InitializeContainer(culture.Name, "GregorianCalendar", TimeZoneInfo.Utc);
|
||||
var formats = container.Resolve<IDateTimeFormatProvider>();
|
||||
var target = container.Resolve<IDateFormatter>();
|
||||
|
||||
@@ -603,7 +602,7 @@ namespace Orchard.Framework.Tests.Localization {
|
||||
|
||||
var allCultures = CultureInfo.GetCultures(CultureTypes.AllCultures);
|
||||
Parallel.ForEach(allCultures, options, culture => { // All cultures on the machine.
|
||||
var container = InitializeContainer(culture.Name, null, TimeZoneInfo.Utc);
|
||||
var container = TestHelpers.InitializeContainer(culture.Name, null, TimeZoneInfo.Utc);
|
||||
var formats = container.Resolve<IDateTimeFormatProvider>();
|
||||
var target = container.Resolve<IDateFormatter>();
|
||||
|
||||
@@ -682,73 +681,5 @@ namespace Orchard.Framework.Tests.Localization {
|
||||
expectedOffset
|
||||
);
|
||||
}
|
||||
|
||||
private IContainer InitializeContainer(string cultureName, string calendarName, TimeZoneInfo timeZone) {
|
||||
var builder = new ContainerBuilder();
|
||||
builder.RegisterInstance<WorkContext>(new StubWorkContext(cultureName, calendarName, timeZone));
|
||||
builder.RegisterType<StubWorkContextAccessor>().As<IWorkContextAccessor>();
|
||||
builder.RegisterType<CultureDateTimeFormatProvider>().As<IDateTimeFormatProvider>();
|
||||
builder.RegisterType<DefaultDateFormatter>().As<IDateFormatter>();
|
||||
builder.RegisterInstance(new Mock<ICalendarSelector>().Object);
|
||||
builder.RegisterType<DefaultCalendarManager>().As<ICalendarManager>();
|
||||
return builder.Build();
|
||||
}
|
||||
|
||||
private class StubWorkContext : WorkContext {
|
||||
|
||||
private string _cultureName;
|
||||
private string _calendarName;
|
||||
private TimeZoneInfo _timeZone;
|
||||
|
||||
public StubWorkContext(string cultureName, string calendarName, TimeZoneInfo timeZone) {
|
||||
_cultureName = cultureName;
|
||||
_calendarName = calendarName;
|
||||
_timeZone = timeZone;
|
||||
}
|
||||
|
||||
public override T Resolve<T>() {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override bool TryResolve<T>(out T service) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override T GetState<T>(string name) {
|
||||
if (name == "CurrentCulture") return (T)((object)_cultureName);
|
||||
if (name == "CurrentCalendar") return (T)((object)_calendarName);
|
||||
if (name == "CurrentTimeZone") return (T)((object)_timeZone);
|
||||
throw new NotImplementedException(String.Format("Property '{0}' is not implemented.", name));
|
||||
}
|
||||
|
||||
public override void SetState<T>(string name, T value) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
private class StubWorkContextAccessor : IWorkContextAccessor {
|
||||
|
||||
private WorkContext _workContext;
|
||||
|
||||
public StubWorkContextAccessor(WorkContext workContext) {
|
||||
_workContext = workContext;
|
||||
}
|
||||
|
||||
public WorkContext GetContext(System.Web.HttpContextBase httpContext) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IWorkContextScope CreateWorkContextScope(System.Web.HttpContextBase httpContext) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public WorkContext GetContext() {
|
||||
return _workContext;
|
||||
}
|
||||
|
||||
public IWorkContextScope CreateWorkContextScope() {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,219 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Autofac;
|
||||
using NUnit.Framework;
|
||||
using Orchard.Localization.Models;
|
||||
using Orchard.Localization.Services;
|
||||
|
||||
namespace Orchard.Tests.Localization {
|
||||
|
||||
[TestFixture]
|
||||
public class DefaultDateLocalizationServicesTests {
|
||||
|
||||
[SetUp]
|
||||
public void Init() {
|
||||
//Regex.CacheSize = 1024;
|
||||
}
|
||||
|
||||
[Test]
|
||||
[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);
|
||||
var result = target.ConvertToSiteTimeZone(dateTimeUtc);
|
||||
Assert.AreEqual(14, result.Day);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[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);
|
||||
var result = target.ConvertToSiteTimeZone(dateTimeUtc);
|
||||
Assert.AreEqual(16, result.Day);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[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);
|
||||
var result = target.ConvertToSiteTimeZone(dateTimeUtc);
|
||||
Assert.AreEqual(DateTimeKind.Local, result.Kind);
|
||||
Assert.AreEqual(dateTimeUtc.Hour + timeZone.BaseUtcOffset.Hours, result.Hour);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[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);
|
||||
var result = target.ConvertToSiteTimeZone(dateTimeUtc);
|
||||
Assert.AreEqual(DateTimeKind.Utc, result.Kind);
|
||||
Assert.AreEqual(dateTimeUtc, result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[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);
|
||||
var result = target.ConvertToSiteTimeZone(dateTimeUtc);
|
||||
Assert.AreEqual(DateTimeKind.Local, result.Kind);
|
||||
Assert.AreEqual(dateTimeUtc.Hour + timeZone.BaseUtcOffset.Hours, result.Hour);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[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);
|
||||
var result = target.ConvertToSiteTimeZone(dateTimeUtc);
|
||||
Assert.AreEqual(DateTimeKind.Utc, result.Kind);
|
||||
Assert.AreEqual(dateTimeUtc, result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[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);
|
||||
var result = target.ConvertToSiteTimeZone(dateTimeUtc);
|
||||
Assert.AreEqual(DateTimeKind.Local, result.Kind);
|
||||
Assert.AreEqual(dateTimeUtc, result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Description("Resulting DateTime is DateTimeKind.Local even when target time zone is not configured time zone of local computer.")]
|
||||
public void ConvertToSiteTimeZoneTest08() {
|
||||
var timeZone = TimeZoneInfo.FindSystemTimeZoneById("Central European Standard Time");
|
||||
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);
|
||||
var result = target.ConvertToSiteTimeZone(dateTimeUtc);
|
||||
Assert.AreEqual(DateTimeKind.Local, result.Kind);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[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);
|
||||
var result = target.ConvertFromSiteTimeZone(dateTimeLocal);
|
||||
Assert.AreEqual(16, result.Day);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[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);
|
||||
var result = target.ConvertFromSiteTimeZone(dateTimeLocal);
|
||||
Assert.AreEqual(14, result.Day);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[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);
|
||||
var result = target.ConvertFromSiteTimeZone(dateTimeLocal);
|
||||
Assert.AreEqual(DateTimeKind.Utc, result.Kind);
|
||||
Assert.AreEqual(dateTimeLocal.Hour - timeZone.BaseUtcOffset.Hours, result.Hour);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[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);
|
||||
var result = target.ConvertFromSiteTimeZone(dateTimeLocal);
|
||||
Assert.AreEqual(DateTimeKind.Utc, result.Kind);
|
||||
Assert.AreEqual(dateTimeLocal.Hour, result.Hour);
|
||||
Assert.AreEqual(dateTimeLocal.Minute, result.Minute);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[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);
|
||||
var result = target.ConvertFromSiteTimeZone(dateTimeLocal);
|
||||
Assert.AreEqual(DateTimeKind.Utc, result.Kind);
|
||||
Assert.AreEqual(dateTimeLocal.Hour - timeZone.BaseUtcOffset.Hours, result.Hour);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[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);
|
||||
var result = target.ConvertFromSiteTimeZone(dateTimeLocal);
|
||||
Assert.AreEqual(DateTimeKind.Utc, result.Kind);
|
||||
Assert.AreEqual(dateTimeLocal.Hour, result.Hour);
|
||||
Assert.AreEqual(dateTimeLocal.Minute, result.Minute);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[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);
|
||||
var result = target.ConvertFromSiteTimeZone(dateTimeLocal);
|
||||
Assert.AreEqual(DateTimeKind.Utc, result.Kind);
|
||||
Assert.AreEqual(dateTimeLocal, result);
|
||||
}
|
||||
}
|
||||
}
|
85
src/Orchard.Tests/Localization/TestHelpers.cs
Normal file
85
src/Orchard.Tests/Localization/TestHelpers.cs
Normal file
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Autofac;
|
||||
using Moq;
|
||||
using Orchard.Localization.Services;
|
||||
using Orchard.Services;
|
||||
using Orchard.Tests.Stubs;
|
||||
|
||||
namespace Orchard.Tests.Localization {
|
||||
|
||||
internal class TestHelpers {
|
||||
public static IContainer InitializeContainer(string cultureName, string calendarName, TimeZoneInfo timeZone) {
|
||||
var builder = new ContainerBuilder();
|
||||
builder.RegisterType<StubClock>().As<IClock>();
|
||||
builder.RegisterInstance<WorkContext>(new StubWorkContext(cultureName, calendarName, timeZone));
|
||||
builder.RegisterType<StubWorkContextAccessor>().As<IWorkContextAccessor>();
|
||||
builder.RegisterType<CultureDateTimeFormatProvider>().As<IDateTimeFormatProvider>();
|
||||
builder.RegisterType<DefaultDateFormatter>().As<IDateFormatter>();
|
||||
builder.RegisterInstance(new Mock<ICalendarSelector>().Object);
|
||||
builder.RegisterType<DefaultCalendarManager>().As<ICalendarManager>();
|
||||
builder.RegisterType<DefaultDateLocalizationServices>().As<IDateLocalizationServices>();
|
||||
return builder.Build();
|
||||
}
|
||||
}
|
||||
|
||||
internal class StubWorkContext : WorkContext {
|
||||
|
||||
private string _cultureName;
|
||||
private string _calendarName;
|
||||
private TimeZoneInfo _timeZone;
|
||||
|
||||
public StubWorkContext(string cultureName, string calendarName, TimeZoneInfo timeZone) {
|
||||
_cultureName = cultureName;
|
||||
_calendarName = calendarName;
|
||||
_timeZone = timeZone;
|
||||
}
|
||||
|
||||
public override T Resolve<T>() {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override bool TryResolve<T>(out T service) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override T GetState<T>(string name) {
|
||||
if (name == "CurrentCulture") return (T)((object)_cultureName);
|
||||
if (name == "CurrentCalendar") return (T)((object)_calendarName);
|
||||
if (name == "CurrentTimeZone") return (T)((object)_timeZone);
|
||||
throw new NotImplementedException(String.Format("Property '{0}' is not implemented.", name));
|
||||
}
|
||||
|
||||
public override void SetState<T>(string name, T value) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
internal class StubWorkContextAccessor : IWorkContextAccessor {
|
||||
|
||||
private WorkContext _workContext;
|
||||
|
||||
public StubWorkContextAccessor(WorkContext workContext) {
|
||||
_workContext = workContext;
|
||||
}
|
||||
|
||||
public WorkContext GetContext(System.Web.HttpContextBase httpContext) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IWorkContextScope CreateWorkContextScope(System.Web.HttpContextBase httpContext) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public WorkContext GetContext() {
|
||||
return _workContext;
|
||||
}
|
||||
|
||||
public IWorkContextScope CreateWorkContextScope() {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
@@ -260,7 +260,9 @@
|
||||
<Compile Include="FileSystems\VirtualPath\DefaultVirtualPathProviderTests.cs" />
|
||||
<Compile Include="Localization\CultureManagerTests.cs" />
|
||||
<Compile Include="Localization\DateTimePartsTests.cs" />
|
||||
<Compile Include="Localization\DefaultDateLocalizationServicesTests.cs" />
|
||||
<Compile Include="Localization\DefaultDateFormatterTests.cs" />
|
||||
<Compile Include="Localization\TestHelpers.cs" />
|
||||
<Compile Include="Logging\OrchardFileAppenderTests.cs" />
|
||||
<Compile Include="Messaging\MessagingChannelStub.cs" />
|
||||
<Compile Include="Mvc\Html\HtmlHelperExtensionsTests.cs" />
|
||||
|
@@ -81,7 +81,7 @@ namespace Orchard.Tokens.Providers {
|
||||
var time = _clock.UtcNow - dateTimeUtc.ToUniversalTime();
|
||||
|
||||
if (time.TotalDays > 7)
|
||||
return _dateFormatter.FormatDateTime(DateTimeParts.FromDateTime(dateTimeUtc), T("'on' MMM d yyyy 'at' h:mm tt").ToString());
|
||||
return _dateLocalizationServices.ConvertToLocalizedString(dateTimeUtc, T("'on' MMM d yyyy 'at' h:mm tt").Text);
|
||||
if (time.TotalHours > 24)
|
||||
return T.Plural("1 day ago", "{0} days ago", time.Days).ToString();
|
||||
if (time.TotalMinutes > 60)
|
||||
|
@@ -28,14 +28,26 @@ namespace Orchard.Localization.Services {
|
||||
_calendarManager = calendarManager;
|
||||
}
|
||||
|
||||
public virtual DateTime ConvertToSiteTimeZone(DateTime date) {
|
||||
var workContext = _workContextAccessor.GetContext();
|
||||
return TimeZoneInfo.ConvertTimeFromUtc(date, workContext.CurrentTimeZone);
|
||||
public virtual DateTime ConvertToSiteTimeZone(DateTime dateUtc) {
|
||||
if (dateUtc.Kind == DateTimeKind.Local) {
|
||||
return dateUtc;
|
||||
}
|
||||
if (CurrentTimeZone == TimeZoneInfo.Utc) {
|
||||
if (dateUtc.Kind == DateTimeKind.Unspecified) {
|
||||
return new DateTime(dateUtc.Ticks, DateTimeKind.Utc);
|
||||
}
|
||||
return dateUtc;
|
||||
}
|
||||
var dateLocal = dateUtc + CurrentTimeZone.BaseUtcOffset;
|
||||
return new DateTime(dateLocal.Ticks, DateTimeKind.Local);
|
||||
}
|
||||
|
||||
public virtual DateTime ConvertFromSiteTimeZone(DateTime date) {
|
||||
var workContext = _workContextAccessor.GetContext();
|
||||
return TimeZoneInfo.ConvertTimeToUtc(date, workContext.CurrentTimeZone);
|
||||
public virtual DateTime ConvertFromSiteTimeZone(DateTime dateLocal) {
|
||||
if (dateLocal.Kind == DateTimeKind.Utc) {
|
||||
return dateLocal;
|
||||
}
|
||||
var dateUtc = dateLocal - CurrentTimeZone.BaseUtcOffset;
|
||||
return new DateTime(dateUtc.Ticks, DateTimeKind.Utc);
|
||||
}
|
||||
|
||||
public virtual DateTimeParts ConvertToSiteCalendar(DateTime date, TimeSpan offset) {
|
||||
@@ -48,12 +60,21 @@ namespace Orchard.Localization.Services {
|
||||
calendar.GetMinute(date),
|
||||
calendar.GetSecond(date),
|
||||
Convert.ToInt32(calendar.GetMilliseconds(date)),
|
||||
DateTimeKind.Utc,
|
||||
date.Kind,
|
||||
offset);
|
||||
}
|
||||
|
||||
public virtual DateTime ConvertFromSiteCalendar(DateTimeParts parts) {
|
||||
return CurrentCalendar.ToDateTime(parts.Date.Year, parts.Date.Month, parts.Date.Day, parts.Time.Hour, parts.Time.Minute, parts.Time.Second, parts.Time.Millisecond);
|
||||
return new DateTime(
|
||||
parts.Date.Year,
|
||||
parts.Date.Month,
|
||||
parts.Date.Day,
|
||||
parts.Time.Hour,
|
||||
parts.Time.Minute,
|
||||
parts.Time.Second,
|
||||
parts.Time.Millisecond,
|
||||
CurrentCalendar,
|
||||
parts.Time.Kind);
|
||||
}
|
||||
|
||||
public string ConvertToLocalizedDateString(DateTime date, DateLocalizationOptions options = null) {
|
||||
@@ -85,13 +106,11 @@ namespace Orchard.Localization.Services {
|
||||
// * Time zone conversion cannot wrap DateTime.MinValue around to the previous day, resulting in undefined result.
|
||||
// Therefore we convert the date to today's date before the conversion, and back to DateTime.MinValue after.
|
||||
var now = _clock.UtcNow;
|
||||
|
||||
dateValue = new DateTime(now.Year, now.Month, now.Day, dateValue.Hour, dateValue.Minute, dateValue.Second, dateValue.Millisecond, dateValue.Kind);
|
||||
dateValue = ConvertToSiteTimeZone(dateValue);
|
||||
dateValue = new DateTime(DateTime.MinValue.Year, DateTime.MinValue.Month, DateTime.MinValue.Day, dateValue.Hour, dateValue.Minute, dateValue.Second, dateValue.Millisecond, dateValue.Kind);
|
||||
|
||||
var workContext = _workContextAccessor.GetContext();
|
||||
offset = workContext.CurrentTimeZone.BaseUtcOffset;
|
||||
offset = CurrentTimeZone.BaseUtcOffset;
|
||||
}
|
||||
|
||||
var parts = DateTimeParts.FromDateTime(dateValue, offset);
|
||||
@@ -125,8 +144,7 @@ namespace Orchard.Localization.Services {
|
||||
|
||||
if (options.EnableTimeZoneConversion) {
|
||||
dateValue = ConvertToSiteTimeZone(dateValue);
|
||||
var workContext = _workContextAccessor.GetContext();
|
||||
offset = workContext.CurrentTimeZone.BaseUtcOffset;
|
||||
offset = CurrentTimeZone.BaseUtcOffset;
|
||||
}
|
||||
|
||||
var parts = DateTimeParts.FromDateTime(dateValue, offset);
|
||||
@@ -226,6 +244,13 @@ namespace Orchard.Localization.Services {
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual TimeZoneInfo CurrentTimeZone {
|
||||
get {
|
||||
var workContext = _workContextAccessor.GetContext();
|
||||
return workContext.CurrentTimeZone;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual DateTime? ToNullable(DateTime date) {
|
||||
return date == DateTime.MinValue ? new DateTime?() : new DateTime?(date);
|
||||
}
|
||||
|
Reference in New Issue
Block a user