Added 15 unit tests to cover time zone conversion, and fixed a bug that the new tests revealed.

This commit is contained in:
Daniel Stolt
2014-08-04 01:57:37 +02:00
parent 2bf89df915
commit ef5ccaadfe
7 changed files with 360 additions and 98 deletions

View File

@@ -2,7 +2,7 @@
using NUnit.Framework;
using Orchard.Localization.Models;
namespace Orchard.Framework.Tests.Localization {
namespace Orchard.Tests.Localization {
[TestFixture]
public class DateTimePartsTests {

View File

@@ -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();
}
}
}
}

View File

@@ -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);
}
}
}

View 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();
}
}
}

View File

@@ -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" />

View File

@@ -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)

View File

@@ -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);
}