Introduced IDateServices and DefaultDateServices. Extracted date localization logic (time zone conversion, formatting/parsing) from DateTimeFieldDriver to IDateServices.

This commit is contained in:
Daniel Stolt
2013-11-20 02:12:43 +01:00
committed by Sebastien Ros
parent 786312cbcd
commit 14ed42a53e
4 changed files with 227 additions and 47 deletions

View File

@@ -9,21 +9,21 @@ using Orchard.Fields.Settings;
using Orchard.Fields.ViewModels;
using Orchard.ContentManagement.Handlers;
using Orchard.Localization;
using Orchard.Localization.Services;
namespace Orchard.Fields.Drivers {
[UsedImplicitly]
public class DateTimeFieldDriver : ContentFieldDriver<DateTimeField> {
public IOrchardServices Services { get; set; }
private const string TemplateName = "Fields/DateTime.Edit"; // EditorTemplates/Fields/DateTime.Edit.cshtml
private readonly Lazy<CultureInfo> _cultureInfo;
public DateTimeFieldDriver(IOrchardServices services) {
public DateTimeFieldDriver(IOrchardServices services, IDateServices dateServices) {
Services = services;
DateServices = dateServices;
T = NullLocalizer.Instance;
_cultureInfo = new Lazy<CultureInfo>(() => CultureInfo.GetCultureInfo(Services.WorkContext.CurrentCulture));
}
public IOrchardServices Services { get; set; }
public IDateServices DateServices { get; set; }
public Localizer T { get; set; }
private static string GetPrefix(ContentField field, ContentPart part) {
@@ -36,16 +36,15 @@ namespace Orchard.Fields.Drivers {
protected override DriverResult Display(ContentPart part, DateTimeField field, string displayType, dynamic shapeHelper) {
return ContentShape("Fields_DateTime", // this is just a key in the Shape Table
GetDifferentiator(field, part),
GetDifferentiator(field, part),
() => {
var settings = field.PartFieldDefinition.Settings.GetModel<DateTimeFieldSettings>();
var value = field.DateTime;
var viewModel = new DateTimeFieldViewModel {
Name = field.DisplayName,
Date = value != DateTime.MinValue ? TimeZoneInfo.ConvertTimeFromUtc(value, Services.WorkContext.CurrentTimeZone).ToString("d", _cultureInfo.Value) : String.Empty,
Time = value != DateTime.MinValue ? TimeZoneInfo.ConvertTimeFromUtc(value, Services.WorkContext.CurrentTimeZone).ToString("t", _cultureInfo.Value) : String.Empty,
Date = DateServices.ConvertToLocalDateString(value, String.Empty),
Time = DateServices.ConvertToLocalTimeString(value, String.Empty),
ShowDate = settings.Display == DateTimeFieldDisplays.DateAndTime || settings.Display == DateTimeFieldDisplays.DateOnly,
ShowTime = settings.Display == DateTimeFieldDisplays.DateAndTime || settings.Display == DateTimeFieldDisplays.TimeOnly,
Hint = settings.Hint,
@@ -59,14 +58,13 @@ namespace Orchard.Fields.Drivers {
}
protected override DriverResult Editor(ContentPart part, DateTimeField field, dynamic shapeHelper) {
var settings = field.PartFieldDefinition.Settings.GetModel<DateTimeFieldSettings>();
var value = field.DateTime;
var viewModel = new DateTimeFieldViewModel {
Name = field.DisplayName,
Date = value != DateTime.MinValue ? TimeZoneInfo.ConvertTimeFromUtc(value, Services.WorkContext.CurrentTimeZone).ToString("d", _cultureInfo.Value) : String.Empty,
Time = value != DateTime.MinValue ? TimeZoneInfo.ConvertTimeFromUtc(value, Services.WorkContext.CurrentTimeZone).ToString("t", _cultureInfo.Value) : String.Empty,
Date = DateServices.ConvertToLocalDateString(value, String.Empty),
Time = DateServices.ConvertToLocalTimeString(value, String.Empty),
ShowDate = settings.Display == DateTimeFieldDisplays.DateAndTime || settings.Display == DateTimeFieldDisplays.DateOnly,
ShowTime = settings.Display == DateTimeFieldDisplays.DateAndTime || settings.Display == DateTimeFieldDisplays.TimeOnly,
Hint = settings.Hint,
@@ -74,46 +72,32 @@ namespace Orchard.Fields.Drivers {
};
return ContentShape("Fields_DateTime_Edit", GetDifferentiator(field, part),
() => shapeHelper.EditorTemplate(TemplateName: TemplateName, Model: viewModel, Prefix: GetPrefix(field, part)));
() => shapeHelper.EditorTemplate(TemplateName: TemplateName, Model: viewModel, Prefix: GetPrefix(field, part)));
}
protected override DriverResult Editor(ContentPart part, DateTimeField field, IUpdateModel updater, dynamic shapeHelper) {
var viewModel = new DateTimeFieldViewModel();
if(updater.TryUpdateModel(viewModel, GetPrefix(field, part), null, null)) {
DateTime value;
if (updater.TryUpdateModel(viewModel, GetPrefix(field, part), null, null)) {
var settings = field.PartFieldDefinition.Settings.GetModel<DateTimeFieldSettings>();
if (settings.Display == DateTimeFieldDisplays.DateOnly) {
viewModel.Time = new DateTime(1980, 1, 1).ToString("t", _cultureInfo.Value);
}
if (settings.Display == DateTimeFieldDisplays.TimeOnly) {
viewModel.Date = new DateTime(1980, 1, 1).ToString("d", _cultureInfo.Value);
}
string parseDateTime = String.Concat(viewModel.Date, " ", viewModel.Time);
if(settings.Required && (String.IsNullOrWhiteSpace(viewModel.Time) || String.IsNullOrWhiteSpace(viewModel.Date))) {
updater.AddModelError(GetPrefix(field, part), T("{0} is required", field.DisplayName));
}
if(!settings.Required
&& (settings.Display != DateTimeFieldDisplays.TimeOnly && String.IsNullOrWhiteSpace(viewModel.Date))
|| (settings.Display != DateTimeFieldDisplays.DateOnly && String.IsNullOrWhiteSpace(viewModel.Time))
) {
field.DateTime = DateTime.MinValue;
}
else if (DateTime.TryParse(parseDateTime, _cultureInfo.Value, DateTimeStyles.None, out value)) {
field.DateTime = TimeZoneInfo.ConvertTimeToUtc(value, Services.WorkContext.CurrentTimeZone);
}
else {
updater.AddModelError(GetPrefix(field, part), T("{0} is an invalid date and time", field.DisplayName));
field.DateTime = DateTime.MinValue;
if (settings.Required && (((settings.Display == DateTimeFieldDisplays.DateAndTime || settings.Display == DateTimeFieldDisplays.DateOnly) && String.IsNullOrWhiteSpace(viewModel.Date)) || ((settings.Display == DateTimeFieldDisplays.DateAndTime || settings.Display == DateTimeFieldDisplays.TimeOnly) && String.IsNullOrWhiteSpace(viewModel.Time)))) {
updater.AddModelError(GetPrefix(field, part), T("{0} is required.", field.DisplayName));
} else {
try {
var utcDateTime = DateServices.ConvertFromLocalString(viewModel.Date, viewModel.Time);
if (utcDateTime.HasValue) {
field.DateTime = utcDateTime.Value;
} else {
field.DateTime = DateTime.MinValue;
}
}
catch (FormatException) {
updater.AddModelError(GetPrefix(field, part), T("{0} could not be parsed as a valid date and time.", field.DisplayName));
}
}
}
return Editor(part, field, shapeHelper);
}
@@ -127,10 +111,8 @@ namespace Orchard.Fields.Drivers {
protected override void Describe(DescribeMembersContext context) {
context
.Member(null, typeof(DateTime), T("Value"), T("The date time value of the field."))
.Enumerate<DateTimeField>(() => field => new[] { field.DateTime })
;
.Member(null, typeof(DateTime), T("Value"), T("The date and time value of the field."))
.Enumerate<DateTimeField>(() => field => new[] { field.DateTime });
}
}
}

View File

@@ -0,0 +1,91 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Orchard;
namespace Orchard.Localization.Services {
public class DefaultDateServices : IDateServices {
public DefaultDateServices(IOrchardServices orchardServices) {
_orchardServices = orchardServices;
_cultureInfo = new Lazy<CultureInfo>(() => CultureInfo.GetCultureInfo(_orchardServices.WorkContext.CurrentCulture));
}
private readonly IOrchardServices _orchardServices;
private readonly Lazy<CultureInfo> _cultureInfo;
public DateTime? ConvertToLocal(DateTime date) {
return ConvertToLocal(ToNullable(date));
}
public DateTime? ConvertToLocal(DateTime? date) {
if (!date.HasValue) {
return null;
}
return TimeZoneInfo.ConvertTimeFromUtc(date.Value, _orchardServices.WorkContext.CurrentTimeZone);
}
public string ConvertToLocalString(DateTime date, string format, string nullText = null) {
return ConvertToLocalString(ToNullable(date), format, nullText);
}
public string ConvertToLocalString(DateTime? date, string format, string nullText = null) {
var localDate = ConvertToLocal(date);
if (!localDate.HasValue) {
return nullText;
}
return localDate.Value.ToString(format, _cultureInfo.Value);
}
public string ConvertToLocalDateString(DateTime date, string nullText = null) {
return ConvertToLocalDateString(ToNullable(date), nullText);
}
public string ConvertToLocalDateString(DateTime? date, string nullText = null) {
return ConvertToLocalString(date, "d", nullText);
}
public string ConvertToLocalTimeString(DateTime date, string nullText = null) {
return ConvertToLocalTimeString(ToNullable(date), nullText);
}
public string ConvertToLocalTimeString(DateTime? date, string nullText = null) {
return ConvertToLocalString(date, "t", nullText);
}
public DateTime? ConvertFromLocal(DateTime date) {
return ConvertToLocal(ToNullable(date));
}
public DateTime? ConvertFromLocal(DateTime? date) {
if (!date.HasValue) {
return null;
}
return TimeZoneInfo.ConvertTimeToUtc(date.Value, _orchardServices.WorkContext.CurrentTimeZone);
}
public DateTime? ConvertFromLocalString(string dateString) {
if (String.IsNullOrWhiteSpace(dateString)) {
return null;
}
var localDate = DateTime.Parse(dateString, _cultureInfo.Value);
return ConvertFromLocal(localDate);
}
public DateTime? ConvertFromLocalString(string dateString, string timeString) {
if (String.IsNullOrWhiteSpace(dateString) && String.IsNullOrWhiteSpace(timeString)) {
return null;
}
var localDate = !String.IsNullOrWhiteSpace(dateString) ? DateTime.Parse(dateString, _cultureInfo.Value) : new DateTime(1980, 1, 1);
var localTime = !String.IsNullOrWhiteSpace(timeString) ? DateTime.Parse(timeString, _cultureInfo.Value) : new DateTime(1980, 1, 1, 12, 0, 0);
var localDateTime = new DateTime(localDate.Year, localDate.Month, localDate.Day, localTime.Hour, localTime.Minute, localTime.Second);
return ConvertFromLocal(localDateTime);
}
private DateTime? ToNullable(DateTime date) {
return date == DateTime.MinValue ? new DateTime?() : new DateTime?(date);
}
}
}

View File

@@ -0,0 +1,105 @@
using System;
namespace Orchard.Localization.Services {
/// <summary>
/// Provides conversion and formatting of dates according to the Orchard configured
/// time zone, culture and calendar (as opposed to the system configured time zone and
/// culture).
/// </summary>
public interface IDateServices : IDependency {
/// <summary>
/// Converts a non-nullable date from Gregorian calendar UTC to the Orchard configured calendar and time zone.
/// </summary>
/// <param name="date">The non-nullable UTC date to convert. DateTime.MinValue is translated to null.</param>
/// <returns></returns>
DateTime? ConvertToLocal(DateTime date);
/// <summary>
/// Converts a nullable date from Gregorian calendar UTC to the Orchard configured calendar and time zone.
/// </summary>
/// <param name="date">The nullable UTC date to convert.</param>
/// <returns></returns>
DateTime? ConvertToLocal(DateTime? date);
/// <summary>
/// Converts a non-nullable date from Gregorian calendar UTC to the Orchard configured calendar and time zone and formats it using the specified format string using the Orchard configured culture.
/// </summary>
/// <param name="date">The non-nullable UTC date to convert. DateTime.MinValue is translated to null.</param>
/// <param name="format">A standard DateTime format string to use for formating the converted date.</param>
/// <param name="nullText">A text to be returned if the supplied UTC date is equal to DateTime.MinValue.</param>
/// <returns></returns>
string ConvertToLocalString(DateTime date, string format, string nullText = null);
/// <summary>
/// Converts a nullable date from Gregorian calendar UTC to the Orchard configured calendar and time zone and formats it using the specified format string using the Orchard configured culture.
/// </summary>
/// <param name="date">The nullable UTC date to convert.</param>
/// <param name="format">A standard DateTime format string to use for formating the converted date.</param>
/// <param name="nullText">A text to be returned if the supplied UTC date has no value.</param>
/// <returns></returns>
string ConvertToLocalString(DateTime? date, string format, string nullText = null);
/// <summary>
/// Converts a non-nullable date from Gregorian calendar UTC to the Orchard configured calendar and time zone and formats it as a date-only string using the Orchard configured culture.
/// </summary>
/// <param name="date">The non-nullable UTC date to convert. DateTime.MinValue is translated to null.</param>
/// <param name="nullText">A text to be returned if the supplied UTC date is equal to DateTime.MinValue.</param>
/// <returns></returns>
string ConvertToLocalDateString(DateTime date, string nullText = null);
/// <summary>
/// Converts a nullable date from Gregorian calendar UTC to the Orchard configured calendar and time zone and formats it as a date-only string using the Orchard configured culture.
/// </summary>
/// <param name="date">The nullable UTC date to convert.</param>
/// <param name="nullText">A text to be returned if the supplied UTC date has no value.</param>
/// <returns></returns>
string ConvertToLocalDateString(DateTime? date, string nullText = null);
/// <summary>
/// Converts a non-nullable date from Gregorian calendar UTC to the Orchard configured calendar and time zone and formats it as a time-only string using the Orchard configured culture.
/// </summary>
/// <param name="date">The non-nullable UTC date to convert. DateTime.MinValue is translated to null.</param>
/// <param name="nullText">A text to be returned if the supplied UTC date is equal to DateTime.MinValue.</param>
/// <returns></returns>
string ConvertToLocalTimeString(DateTime date, string nullText = null);
/// <summary>
/// Converts a nullable date from Gregorian calendar UTC to the Orchard configured calendar and time zone and formats it as a time-only string using the Orchard configured culture.
/// </summary>
/// <param name="date">The nullable UTC date to convert.</param>
/// <param name="nullText">A text to be returned if the supplied UTC date has no value.</param>
/// <returns></returns>
string ConvertToLocalTimeString(DateTime? date, string nullText = null);
/// <summary>
/// Converts a non-nullable date to Gregorian calendar UTC from the Orchard configured calendar and time zone.
/// </summary>
/// <param name="date">The non-nullable UTC date to convert. DateTime.MinValue is translated to null.</param>
/// <returns></returns>
DateTime? ConvertFromLocal(DateTime date);
/// <summary>
/// Converts a nullable date from Gregorian calendar UTC to the Orchard configured calendar and time zone.
/// </summary>
/// <param name="date">The nullable UTC date to convert.</param>
/// <returns></returns>
DateTime? ConvertFromLocal(DateTime? date);
/// <summary>
/// Parses a date and time string using the Orchard configured culture and converts it to Gregorian calendar UTC from the Orchard configured calendar and time zone.
/// </summary>
/// <param name="dateString">The local date and time string to parse and convert.</param>
/// <returns></returns>
DateTime? ConvertFromLocalString(string dateString);
/// <summary>
/// Parses separate date and time strings using the Orchard configured culture and converts the resulting combined DateTime to Gregorian calendar UTC from the Orchard configured calendar and time zone.
/// </summary>
/// <param name="dateString">The local date string to parse and convert, or null or an empty string to only convert the time component.</param>
/// <param name="timeString">The local time string to parse and convert, or null or an empty string to only convert the date component.</param>
/// <returns></returns>
DateTime? ConvertFromLocalString(string dateString, string timeString);
}
}

View File

@@ -267,7 +267,9 @@
<Compile Include="FileSystems\Media\IMimeTypeProvider.cs" />
<Compile Include="Indexing\ISearchBits.cs" />
<Compile Include="Localization\Services\CurrentCultureWorkContext.cs" />
<Compile Include="Localization\Services\DefaultDateServices.cs" />
<Compile Include="Localization\Services\DefaultLocalizedStringManager.cs" />
<Compile Include="Localization\Services\IDateServices.cs" />
<Compile Include="Localization\Services\ILocalizedStringManager.cs" />
<Compile Include="Logging\OrchardFileAppender.cs" />
<Compile Include="Logging\OrchardLog4netFactory.cs" />