Did initial draft rewrite of DefaultDateLocalizationServices.

This commit is contained in:
Daniel Stolt
2014-08-02 03:19:34 +02:00
parent 5d10ed1007
commit 3175a280ac
17 changed files with 299 additions and 212 deletions

View File

@@ -8,12 +8,12 @@ using Orchard.Localization.Services;
namespace Orchard.Core.Common.DateEditor {
public class DateEditorDriver : ContentPartDriver<CommonPart> {
private readonly IDateLocalizationServices _dateServices;
private readonly IDateLocalizationServices _dateLocalizationServices;
public DateEditorDriver(
IOrchardServices services,
IDateLocalizationServices dateServices) {
_dateServices = dateServices;
IDateLocalizationServices dateLocalizationServices) {
_dateLocalizationServices = dateLocalizationServices;
T = NullLocalizer.Instance;
Services = services;
}
@@ -59,8 +59,8 @@ namespace Orchard.Core.Common.DateEditor {
theDatesHaveNotBeenModified;
if (!theEditorShouldBeBlank) {
model.Editor.Date = _dateServices.ConvertToLocalDateString(part.CreatedUtc, "");
model.Editor.Time = _dateServices.ConvertToLocalTimeString(part.CreatedUtc, "");
model.Editor.Date = _dateLocalizationServices.ConvertToLocalizedDateString(part.CreatedUtc);
model.Editor.Time = _dateLocalizationServices.ConvertToLocalizedTimeString(part.CreatedUtc);
}
}
@@ -69,7 +69,7 @@ namespace Orchard.Core.Common.DateEditor {
if (!String.IsNullOrWhiteSpace(model.Editor.Date) && !String.IsNullOrWhiteSpace(model.Editor.Time)) {
try {
var utcDateTime = _dateServices.ConvertFromLocalString(model.Editor.Date, model.Editor.Time);
var utcDateTime = _dateLocalizationServices.ConvertFromLocalizedString(model.Editor.Date, model.Editor.Time);
part.CreatedUtc = utcDateTime;
part.VersionCreatedUtc = utcDateTime;
}

View File

@@ -11,16 +11,16 @@ using Orchard.Services;
namespace Orchard.Core.Shapes {
public class DateTimeShapes : IDependency {
private readonly IClock _clock;
private readonly IDateLocalizationServices _dateServices;
private readonly IDateLocalizationServices _dateLocalizationServices;
private readonly IDateTimeFormatProvider _dateTimeLocalization;
public DateTimeShapes(
IClock clock,
IDateLocalizationServices dateServices,
IDateLocalizationServices dateLocalizationServices,
IDateTimeFormatProvider dateTimeLocalization
) {
_clock = clock;
_dateServices = dateServices;
_dateLocalizationServices = dateLocalizationServices;
_dateTimeLocalization = dateTimeLocalization;
T = NullLocalizer.Instance;
}
@@ -65,10 +65,10 @@ namespace Orchard.Core.Shapes {
//using a LocalizedString forces the caller to use a localizable format
if (CustomFormat == null || String.IsNullOrWhiteSpace(CustomFormat.Text)) {
return new MvcHtmlString(_dateServices.ConvertToLocalString(DateTimeUtc, _dateTimeLocalization.LongDateTimeFormat, null));
return new MvcHtmlString(_dateLocalizationServices.ConvertToLocalizedString(DateTimeUtc, _dateTimeLocalization.LongDateTimeFormat));
}
return new MvcHtmlString(_dateServices.ConvertToLocalString(DateTimeUtc, CustomFormat.Text, null));
return new MvcHtmlString(_dateLocalizationServices.ConvertToLocalizedString(DateTimeUtc, CustomFormat.Text));
}
}
}

View File

@@ -14,14 +14,14 @@ namespace Orchard.ArchiveLater.Drivers {
public class ArchiveLaterPartDriver : ContentPartDriver<ArchiveLaterPart> {
private const string TemplateName = "Parts/ArchiveLater";
private readonly IArchiveLaterService _archiveLaterService;
private readonly IDateLocalizationServices _dateServices;
private readonly IDateLocalizationServices _dateLocalizationServices;
public ArchiveLaterPartDriver(
IOrchardServices services,
IArchiveLaterService archiveLaterService,
IDateLocalizationServices dateServices) {
IDateLocalizationServices dateLocalizationServices) {
_archiveLaterService = archiveLaterService;
_dateServices = dateServices;
_dateLocalizationServices = dateLocalizationServices;
T = NullLocalizer.Instance;
Services = services;
}
@@ -56,8 +56,8 @@ namespace Orchard.ArchiveLater.Drivers {
Editor = new DateTimeEditor() {
ShowDate = true,
ShowTime = true,
Date = _dateServices.ConvertToLocalDateString(part.ScheduledArchiveUtc.Value, ""),
Time = _dateServices.ConvertToLocalTimeString(part.ScheduledArchiveUtc.Value, ""),
Date = _dateLocalizationServices.ConvertToLocalizedDateString(part.ScheduledArchiveUtc.Value),
Time = _dateLocalizationServices.ConvertToLocalizedTimeString(part.ScheduledArchiveUtc.Value),
}
};
@@ -71,7 +71,7 @@ namespace Orchard.ArchiveLater.Drivers {
if (updater.TryUpdateModel(model, Prefix, null, null)) {
if (model.ArchiveLater) {
try {
var utcDateTime = _dateServices.ConvertFromLocalString(model.Editor.Date, model.Editor.Time);
var utcDateTime = _dateLocalizationServices.ConvertFromLocalizedString(model.Editor.Date, model.Editor.Time);
_archiveLaterService.ArchiveLater(model.ContentItem, utcDateTime.HasValue ? utcDateTime.Value : DateTime.MaxValue);
}
catch (FormatException) {

View File

@@ -17,13 +17,11 @@ namespace Orchard.AuditTrail.Controllers {
private readonly IAuditTrailManager _auditTrailManager;
private readonly IOrchardServices _services;
private readonly IAuditTrailEventDisplayBuilder _displayBuilder;
private readonly IDateServices _dateServices;
public AdminController(IAuditTrailManager auditTrailManager, IOrchardServices services, IAuditTrailEventDisplayBuilder displayBuilder, IDateServices dateServices) {
public AdminController(IAuditTrailManager auditTrailManager, IOrchardServices services, IAuditTrailEventDisplayBuilder displayBuilder) {
_auditTrailManager = auditTrailManager;
_services = services;
_displayBuilder = displayBuilder;
_dateServices = dateServices;
_authorizer = services.Authorizer;
New = _services.New;
}

View File

@@ -4,6 +4,7 @@ using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.Environment.Extensions;
using Orchard.Localization;
using Orchard.Localization.Models;
using Orchard.Localization.Services;
using Orchard.Security;
@@ -11,12 +12,12 @@ namespace Orchard.AuditTrail.Drivers {
[OrchardFeature("Orchard.AuditTrail.Trimming")]
public class AuditTrailTrimmingSettingsPartDriver : ContentPartDriver<AuditTrailTrimmingSettingsPart> {
private readonly IAuthorizer _authorizer;
private readonly IDateServices _dateServices;
private readonly IDateLocalizationServices _dateLocalizationServices;
private readonly IDateTimeFormatProvider _dateTimeLocalization;
public AuditTrailTrimmingSettingsPartDriver(IAuthorizer authorizer, IDateServices dateServices, IDateTimeFormatProvider dateTimeLocalization) {
public AuditTrailTrimmingSettingsPartDriver(IAuthorizer authorizer, IDateLocalizationServices dateLocalizationServices, IDateTimeFormatProvider dateTimeLocalization) {
_authorizer = authorizer;
_dateServices = dateServices;
_dateLocalizationServices = dateLocalizationServices;
_dateTimeLocalization = dateTimeLocalization;
T = NullLocalizer.Instance;
}
@@ -35,7 +36,7 @@ namespace Orchard.AuditTrail.Drivers {
var viewModel = new AuditTrailTrimmingSettingsViewModel {
RetentionPeriod = part.RetentionPeriod,
MinimumRunInterval = part.MinimumRunInterval,
LastRunDateString = _dateServices.ConvertToLocalString(part.LastRunUtc, _dateTimeLocalization.ShortDateTimeFormat, T("Never").Text)
LastRunDateString = _dateLocalizationServices.ConvertToLocalizedString(part.LastRunUtc, _dateTimeLocalization.ShortDateTimeFormat, new DateLocalizationOptions() { NullText = T("Never").Text })
};
if (updater != null) {

View File

@@ -8,11 +8,11 @@ using Orchard.Localization.Services;
namespace Orchard.AuditTrail.Services {
public class CommonAuditTrailEventHandler : AuditTrailEventHandlerBase {
private readonly Lazy<IAuditTrailManager> _auditTrailManager;
private readonly IDateServices _dateServices;
private readonly IDateLocalizationServices _dateLocalizationServices;
public CommonAuditTrailEventHandler(Lazy<IAuditTrailManager> auditTrailManager, IDateServices dateServices) {
public CommonAuditTrailEventHandler(Lazy<IAuditTrailManager> auditTrailManager, IDateLocalizationServices dateLocalizationServices) {
_auditTrailManager = auditTrailManager;
_dateServices = dateServices;
_dateLocalizationServices = dateLocalizationServices;
}
public override void Filter(QueryFilterContext context) {
@@ -60,7 +60,7 @@ namespace Orchard.AuditTrail.Services {
try {
var dateString = filters.Get(prefix + ".Date");
var timeString = filters.Get(prefix + ".Time");
return _dateServices.ConvertFromLocalString(dateString, timeString);
return _dateLocalizationServices.ConvertFromLocalizedString(dateString, timeString);
}
catch (FormatException ex) {
filters.UpdateModel.AddModelError(prefix, T(@"Error parsing ""{0}"" date: {1}", fieldName, ex.Message));

View File

@@ -17,14 +17,14 @@ namespace Orchard.Fields.Drivers {
public class DateTimeFieldDriver : ContentFieldDriver<DateTimeField> {
private const string TemplateName = "Fields/DateTime.Edit"; // EditorTemplates/Fields/DateTime.Edit.cshtml
public DateTimeFieldDriver(IOrchardServices services, IDateLocalizationServices dateServices) {
public DateTimeFieldDriver(IOrchardServices services, IDateLocalizationServices dateLocalizationServices) {
Services = services;
DateServices = dateServices;
DateLocalizationServices = dateLocalizationServices;
T = NullLocalizer.Instance;
}
public IOrchardServices Services { get; set; }
public IDateLocalizationServices DateServices { get; set; }
public IDateLocalizationServices DateLocalizationServices { get; set; }
public Localizer T { get; set; }
private static string GetPrefix(ContentField field, ContentPart part) {
@@ -47,8 +47,8 @@ namespace Orchard.Fields.Drivers {
Hint = settings.Hint,
IsRequired = settings.Required,
Editor = new DateTimeEditor() {
Date = DateServices.ConvertToLocalDateString(value, String.Empty),
Time = DateServices.ConvertToLocalTimeString(value, String.Empty),
Date = DateLocalizationServices.ConvertToLocalizedDateString(value),
Time = DateLocalizationServices.ConvertToLocalizedTimeString(value),
ShowDate = settings.Display == DateTimeFieldDisplays.DateAndTime || settings.Display == DateTimeFieldDisplays.DateOnly,
ShowTime = settings.Display == DateTimeFieldDisplays.DateAndTime || settings.Display == DateTimeFieldDisplays.TimeOnly,
}
@@ -69,8 +69,8 @@ namespace Orchard.Fields.Drivers {
Hint = settings.Hint,
IsRequired = settings.Required,
Editor = new DateTimeEditor() {
Date = DateServices.ConvertToLocalDateString(value, String.Empty),
Time = DateServices.ConvertToLocalTimeString(value, String.Empty),
Date = DateLocalizationServices.ConvertToLocalizedDateString(value),
Time = DateLocalizationServices.ConvertToLocalizedTimeString(value),
ShowDate = settings.Display == DateTimeFieldDisplays.DateAndTime || settings.Display == DateTimeFieldDisplays.DateOnly,
ShowTime = settings.Display == DateTimeFieldDisplays.DateAndTime || settings.Display == DateTimeFieldDisplays.TimeOnly,
}
@@ -90,7 +90,7 @@ namespace Orchard.Fields.Drivers {
updater.AddModelError(GetPrefix(field, part), T("{0} is required.", field.DisplayName));
} else {
try {
var utcDateTime = DateServices.ConvertFromLocalString(viewModel.Editor.Date, viewModel.Editor.Time);
var utcDateTime = DateLocalizationServices.ConvertFromLocalizedString(viewModel.Editor.Date, viewModel.Editor.Time);
if (utcDateTime.HasValue) {
field.DateTime = utcDateTime.Value;
} else {

View File

@@ -18,18 +18,18 @@ namespace Orchard.PublishLater.Drivers {
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IPublishLaterService _publishLaterService;
private readonly IClock _clock;
private readonly IDateLocalizationServices _dateServices;
private readonly IDateLocalizationServices _dateLocalizationServices;
public PublishLaterPartDriver(
IOrchardServices services,
IHttpContextAccessor httpContextAccessor,
IPublishLaterService publishLaterService,
IClock clock,
IDateLocalizationServices dateServices) {
IDateLocalizationServices dateLocalizationServices) {
_httpContextAccessor = httpContextAccessor;
_publishLaterService = publishLaterService;
_clock = clock;
_dateServices = dateServices;
_dateLocalizationServices = dateLocalizationServices;
T = NullLocalizer.Instance;
Services = services;
}
@@ -65,8 +65,8 @@ namespace Orchard.PublishLater.Drivers {
Editor = new DateTimeEditor() {
ShowDate = true,
ShowTime = true,
Date = !part.IsPublished() ? _dateServices.ConvertToLocalDateString(part.ScheduledPublishUtc.Value, "") : "",
Time = !part.IsPublished() ? _dateServices.ConvertToLocalTimeString(part.ScheduledPublishUtc.Value, "") : "",
Date = !part.IsPublished() ? _dateLocalizationServices.ConvertToLocalizedDateString(part.ScheduledPublishUtc.Value) : "",
Time = !part.IsPublished() ? _dateLocalizationServices.ConvertToLocalizedTimeString(part.ScheduledPublishUtc.Value) : "",
}
};
@@ -82,7 +82,7 @@ namespace Orchard.PublishLater.Drivers {
if (httpContext.Request.Form["submit.Save"] == "submit.PublishLater") {
if (!String.IsNullOrWhiteSpace(model.Editor.Date) && !String.IsNullOrWhiteSpace(model.Editor.Time)) {
try {
var utcDateTime = _dateServices.ConvertFromLocalString(model.Editor.Date, model.Editor.Time);
var utcDateTime = _dateLocalizationServices.ConvertFromLocalizedString(model.Editor.Date, model.Editor.Time);
if (utcDateTime.HasValue) {
if (utcDateTime.Value < _clock.UtcNow) {
updater.AddModelError("ScheduledPublishUtcDate", T("You cannot schedule a publishing date in the past."));

View File

@@ -11,7 +11,7 @@ namespace Orchard.Tokens.Providers {
private readonly IDateTimeFormatProvider _dateTimeLocalization;
private readonly IWorkContextAccessor _workContextAccessor;
private readonly Lazy<CultureInfo> _cultureInfo;
private readonly IDateLocalizationServices _dateServices;
private readonly IDateLocalizationServices _dateLocalizationServices;
public DateTokens(
IClock clock,
@@ -22,7 +22,7 @@ namespace Orchard.Tokens.Providers {
_dateTimeLocalization = dateTimeLocalization;
_workContextAccessor = workContextAccessor;
_cultureInfo = new Lazy<CultureInfo>(() => CultureInfo.GetCultureInfo(_workContextAccessor.GetContext().CurrentCulture));
_dateServices = dateServices;
_dateLocalizationServices = dateServices;
T = NullLocalizer.Instance;
}
@@ -45,8 +45,8 @@ namespace Orchard.Tokens.Providers {
.Token("Since", DateTimeRelative)
.Chain("Since", "Date", DateTimeRelative)
// {Date.Local}
.Token("Local", d => _dateServices.ConvertToSiteTimeZone(d))
.Chain("Local", "Date", d => _dateServices.ConvertToSiteTimeZone(d))
.Token("Local", d => _dateLocalizationServices.ConvertToSiteTimeZone(d))
.Chain("Local", "Date", d => _dateLocalizationServices.ConvertToSiteTimeZone(d))
// {Date.ShortDate}
.Token("ShortDate", d => d.ToString(_dateTimeLocalization.ShortDateFormat, _cultureInfo.Value))
// {Date.ShortTime}

View File

@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Orchard.Localization.Models {
public class DateLocalizationOptions {
public DateLocalizationOptions() {
NullText = String.Empty;
EnableTimeZoneConversion = true;
EnableCalendarConversion = true;
}
/// <summary>
/// Gets on sets the string to use in place of a null date when converting to and from a string. The default is an empty string.
/// </summary>
public string NullText { get; set; }
/// <summary>
/// Gets or sets a boolean indicating whether to perform time zone conversion as part of converting a date to and from a string. The default is true.
/// </summary>
public bool EnableTimeZoneConversion { get; set; }
/// <summary>
/// Gets or sets a boolean indicating whether to perform calendar conversion as part of converting a date to and from a string. The default is true.
/// </summary>
public bool EnableCalendarConversion { get; set; }
}
}

View File

@@ -5,6 +5,12 @@ using System.Linq;
namespace Orchard.Localization.Models {
public struct DateParts {
public static DateParts MinValue {
get {
return new DateParts(DateTime.MinValue.Year, DateTime.MinValue.Month, DateTime.MinValue.Day);
}
}
public DateParts(int year, int month, int day) {
_year = year;
_month = month;

View File

@@ -5,6 +5,17 @@ using System.Linq;
namespace Orchard.Localization.Models {
public struct DateTimeParts {
//public static DateTimeParts? FromDateTime(DateTime? dateTime) {
// if (!dateTime.HasValue) {
// return null;
// }
// return FromDateTime(dateTime.Value);
//}
public static DateTimeParts FromDateTime(DateTime dateTime) {
return new DateTimeParts(dateTime.Year, dateTime.Month, dateTime.Day, dateTime.Hour, dateTime.Minute, dateTime.Second, dateTime.Millisecond);
}
public DateTimeParts(int year, int month, int day, int hour, int minute, int second, int millisecond) {
_date = new DateParts(year, month, day);
_time = new TimeParts(hour, minute, second, millisecond);

View File

@@ -5,6 +5,12 @@ using System.Linq;
namespace Orchard.Localization.Models {
public struct TimeParts {
public static TimeParts MinValue {
get {
return new TimeParts(DateTime.MinValue.Hour, DateTime.MinValue.Minute, DateTime.MinValue.Second, DateTime.MinValue.Millisecond);
}
}
public TimeParts(int hour, int minute, int second, int millisecond) {
_hour = hour;
_minute = minute;

View File

@@ -10,169 +10,148 @@ namespace Orchard.Localization.Services {
private readonly IWorkContextAccessor _workContextAccessor;
private readonly IDateTimeFormatProvider _dateTimeFormatProvider;
private readonly IDateFormatter _dateFormatter;
private readonly ICalendarManager _calendarManager;
public DefaultDateLocalizationServices(
IWorkContextAccessor workContextAccessor,
IDateTimeFormatProvider dateTimeFormatProvider,
IDateFormatter dateFormatter,
ICalendarManager calendarManager) {
_workContextAccessor = workContextAccessor;
_dateTimeFormatProvider = dateTimeFormatProvider;
_dateFormatter = dateFormatter;
_calendarManager = calendarManager;
}
public virtual DateTime? ConvertToSiteTimeZone(DateTime date) {
return ConvertToSiteTimeZone(ToNullable(date));
}
public virtual DateTime? ConvertToSiteTimeZone(DateTime? date) {
if (!date.HasValue) {
return null;
}
public virtual DateTime ConvertToSiteTimeZone(DateTime date) {
var workContext = _workContextAccessor.GetContext();
return TimeZoneInfo.ConvertTimeFromUtc(date.Value, workContext.CurrentTimeZone);
return TimeZoneInfo.ConvertTimeFromUtc(date, workContext.CurrentTimeZone);
}
public virtual DateTime? ConvertFromSiteTimeZone(DateTime date) {
return ConvertFromSiteTimeZone(ToNullable(date));
}
public virtual DateTime? ConvertFromSiteTimeZone(DateTime? date) {
if (!date.HasValue) {
return null;
}
public virtual DateTime ConvertFromSiteTimeZone(DateTime date) {
var workContext = _workContextAccessor.GetContext();
return TimeZoneInfo.ConvertTimeToUtc(date.Value, workContext.CurrentTimeZone);
return TimeZoneInfo.ConvertTimeToUtc(date, workContext.CurrentTimeZone);
}
public virtual DateTimeParts? ConvertToSiteCalendar(DateTime? date) {
if (!date.HasValue){
return null;
}
public virtual DateTimeParts ConvertToSiteCalendar(DateTime date) {
var calendar = CurrentCalendar;
return new DateTimeParts(
calendar.GetYear(date.Value),
calendar.GetMonth(date.Value),
calendar.GetDayOfMonth(date.Value),
calendar.GetHour(date.Value),
calendar.GetMinute(date.Value),
calendar.GetSecond(date.Value),
Convert.ToInt32(calendar.GetMilliseconds(date.Value)));
calendar.GetYear(date),
calendar.GetMonth(date),
calendar.GetDayOfMonth(date),
calendar.GetHour(date),
calendar.GetMinute(date),
calendar.GetSecond(date),
Convert.ToInt32(calendar.GetMilliseconds(date)));
}
public virtual DateTime? ConvertFromSiteCalendar(DateTimeParts? parts) {
if (!parts.HasValue) {
return null;
}
return new DateTime(parts.Value.Date.Year, parts.Value.Date.Month, parts.Value.Date.Day, parts.Value.Time.Hour, parts.Value.Time.Minute, parts.Value.Time.Second, parts.Value.Time.Millisecond, CurrentCalendar);
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);
}
public virtual string ConvertToLocalString(DateTime date, string nullText = null) {
return ConvertToLocalString(ToNullable(date), _dateTimeFormatProvider.LongDateTimeFormat, nullText);
public string ConvertToLocalizedDateString(DateTime date, DateLocalizationOptions options = null) {
return ConvertToLocalizedDateString(ToNullable(date), options);
}
public virtual string ConvertToLocalString(DateTime date, string format, string nullText = null) {
return ConvertToLocalString(ToNullable(date), format, nullText);
public string ConvertToLocalizedDateString(DateTime? date, DateLocalizationOptions options = null) {
return ConvertToLocalizedString(date, _dateTimeFormatProvider.ShortDateFormat, options);
}
public virtual string ConvertToLocalString(DateTime? date, string format, string nullText = null) {
var localDate = ConvertToSiteTimeZone(date);
if (!localDate.HasValue) {
return nullText;
public string ConvertToLocalizedTimeString(DateTime date, DateLocalizationOptions options = null) {
return ConvertToLocalizedTimeString(ToNullable(date), options);
}
public string ConvertToLocalizedTimeString(DateTime? date, DateLocalizationOptions options = null) {
return ConvertToLocalizedString(date, _dateTimeFormatProvider.LongTimeFormat, options);
}
public string ConvertToLocalizedString(DateTime date, DateLocalizationOptions options = null) {
return ConvertToLocalizedString(ToNullable(date), options);
}
public string ConvertToLocalizedString(DateTime? date, DateLocalizationOptions options = null) {
return ConvertToLocalizedString(date, _dateTimeFormatProvider.ShortDateTimeFormat, options);
}
public string ConvertToLocalizedString(DateTime date, string format, DateLocalizationOptions options = null) {
return ConvertToLocalizedString(ToNullable(date), format, options);
}
public string ConvertToLocalizedString(DateTime? date, string format, DateLocalizationOptions options = null) {
options = options ?? new DateLocalizationOptions();
if (!date.HasValue) {
return options.NullText;
}
// If the configured current calendar is different from the default calendar
// of the configured current culture we must override the conversion process.
// We do this by using a custom CultureInfo modified to use GregorianCalendar
// (means no calendar conversion will be performed as part of the string
// formatting) and instead perform the calendar conversion ourselves.
var dateValue = date.Value;
var cultureInfo = CurrentCulture;
var usingCultureCalendar = CurrentCulture.DateTimeFormat.Calendar.GetType().IsInstanceOfType(CurrentCalendar);
if (!usingCultureCalendar) {
cultureInfo = (CultureInfo)CurrentCulture.Clone();
cultureInfo.DateTimeFormat.Calendar = new GregorianCalendar();
var calendar = CurrentCalendar;
localDate = new DateTime(calendar.GetYear(localDate.Value), calendar.GetMonth(localDate.Value), calendar.GetDayOfMonth(localDate.Value), calendar.GetHour(localDate.Value), calendar.GetMinute(localDate.Value), calendar.GetSecond(localDate.Value));
if (options.EnableTimeZoneConversion) {
dateValue = ConvertToSiteTimeZone(dateValue);
}
return localDate.Value.ToString(format, cultureInfo);
var parts = DateTimeParts.FromDateTime(dateValue);
if (options.EnableCalendarConversion && !(CurrentCalendar is GregorianCalendar)) {
parts = ConvertToSiteCalendar(dateValue);
}
return _dateFormatter.FormatDateTime(parts, format);
}
public virtual string ConvertToLocalDateString(DateTime date, string nullText = null) {
return ConvertToLocalDateString(ToNullable(date), nullText);
public DateTime? ConvertFromLocalizedDateString(string dateString, DateLocalizationOptions options = null) {
return ConvertFromLocalizedString(dateString, null, options);
}
public virtual string ConvertToLocalDateString(DateTime? date, string nullText = null) {
return ConvertToLocalString(date, _dateTimeFormatProvider.ShortDateFormat, nullText);
public DateTime? ConvertFromLocalizedTimeString(string timeString, DateLocalizationOptions options = null) {
return ConvertFromLocalizedString(null, timeString, options);
}
public virtual string ConvertToLocalTimeString(DateTime date, string nullText = null) {
return ConvertToLocalTimeString(ToNullable(date), nullText);
}
public DateTime? ConvertFromLocalizedString(string dateString, string timeString, DateLocalizationOptions options = null) {
options = options ?? new DateLocalizationOptions();
public virtual string ConvertToLocalTimeString(DateTime? date, string nullText = null) {
return ConvertToLocalString(date, _dateTimeFormatProvider.ShortTimeFormat, nullText);
}
public virtual DateTime? ConvertFromLocalString(string dateString) {
if (String.IsNullOrWhiteSpace(dateString)) {
var hasDate = dateString != null && dateString != options.NullText;
var hasTime = timeString != null && timeString != options.NullText;
if (!hasDate && !hasTime) {
return null;
}
// If the configured current calendar is different from the default calendar
// of the configured current culture we must override the conversion process.
// We do this by using a custom CultureInfo modified to use GregorianCalendar
// (means no calendar conversion will be performed as part of the string
// parsing) and instead perform the calendar conversion ourselves.
var parts = new DateTimeParts(
hasDate ? _dateFormatter.ParseDate(dateString) : DateParts.MinValue,
hasTime ? _dateFormatter.ParseTime(timeString) : TimeParts.MinValue
);
var cultureInfo = CurrentCulture;
var usingCultureCalendar = CurrentCulture.DateTimeFormat.Calendar.GetType().IsInstanceOfType(CurrentCalendar);
if (!usingCultureCalendar) {
cultureInfo = (CultureInfo)CurrentCulture.Clone();
cultureInfo.DateTimeFormat.Calendar = new GregorianCalendar();
var dateValue = parts.ToDateTime();
if (hasDate && options.EnableCalendarConversion && !(CurrentCalendar is GregorianCalendar)) {
dateValue = ConvertFromSiteCalendar(parts);
}
var localDate = DateTime.Parse(dateString, CurrentCulture);
if (!usingCultureCalendar) {
var calendar = CurrentCalendar;
localDate = calendar.ToDateTime(localDate.Year, localDate.Month, localDate.Day, localDate.Hour, localDate.Minute, localDate.Second, localDate.Millisecond);
if (hasTime && options.EnableTimeZoneConversion) {
dateValue = ConvertFromSiteTimeZone(dateValue);
}
return ConvertFromSiteTimeZone(localDate);
return dateValue;
}
public virtual DateTime? ConvertFromLocalString(string dateString, string timeString) {
if (String.IsNullOrWhiteSpace(dateString) && String.IsNullOrWhiteSpace(timeString)) {
public DateTime? ConvertFromLocalizedString(string dateTimeString, DateLocalizationOptions options = null) {
options = options ?? new DateLocalizationOptions();
if (dateTimeString == null || dateTimeString == options.NullText) {
return null;
}
// If the configured current calendar is different from the default calendar
// of the configured current culture we must override the conversion process.
// We do this by using a custom CultureInfo modified to use GregorianCalendar
// (means no calendar conversion will be performed as part of the string
// parsing) and instead perform the calendar conversion ourselves.
var parts = _dateFormatter.ParseDateTime(dateTimeString);
var cultureInfo = CurrentCulture;
var usingCultureCalendar = CurrentCulture.DateTimeFormat.Calendar.GetType().IsInstanceOfType(CurrentCalendar);
if (!usingCultureCalendar) {
cultureInfo = (CultureInfo)CurrentCulture.Clone();
cultureInfo.DateTimeFormat.Calendar = new GregorianCalendar();
var dateValue = parts.ToDateTime();
if (options.EnableCalendarConversion && !(CurrentCalendar is GregorianCalendar)) {
dateValue = ConvertFromSiteCalendar(parts);
}
var localDate = !String.IsNullOrWhiteSpace(dateString) ? DateTime.Parse(dateString, cultureInfo) : new DateTime(1980, 1, 1);
var localTime = !String.IsNullOrWhiteSpace(timeString) ? DateTime.Parse(timeString, cultureInfo) : new DateTime(1980, 1, 1, 12, 0, 0);
var localDateTime = new DateTime(localDate.Year, localDate.Month, localDate.Day, localTime.Hour, localTime.Minute, localTime.Second);
if (!usingCultureCalendar) {
var calendar = CurrentCalendar;
localDateTime = calendar.ToDateTime(localDateTime.Year, localDateTime.Month, localDateTime.Day, localDateTime.Hour, localDateTime.Minute, localDateTime.Second, localDateTime.Millisecond);
if (options.EnableTimeZoneConversion) {
dateValue = ConvertFromSiteTimeZone(dateValue);
}
return ConvertFromSiteTimeZone(localDateTime);
return dateValue;
}
protected virtual CultureInfo CurrentCulture {

View File

@@ -11,120 +11,172 @@ namespace Orchard.Localization.Services {
public interface IDateLocalizationServices : IDependency {
/// <summary>
/// Converts a non-nullable date from UTC to the Orchard configured time zone.
/// Converts a date from UTC to the Orchard configured time zone.
/// </summary>
/// <param name="dateUtc">The non-nullable UTC date to convert. DateTime.MinValue is translated to null.</param>
/// <param name="dateUtc">The UTC date to convert.</param>
/// <returns></returns>
DateTime? ConvertToSiteTimeZone(DateTime dateUtc);
DateTime ConvertToSiteTimeZone(DateTime dateUtc);
///// <summary>
///// Converts a nullable date from UTC to the Orchard configured time zone.
///// </summary>
///// <param name="dateUtc">The nullable UTC date to convert.</param>
///// <returns></returns>
//DateTime? ConvertToSiteTimeZone(DateTime? dateUtc);
/// <summary>
/// Converts a nullable date from UTC to the Orchard configured time zone.
/// Converts a date from the Orchard configured time zone to UTC.
/// </summary>
/// <param name="dateUtc">The nullable UTC date to convert.</param>
/// <param name="dateLocal">The local date to convert.</param>
/// <returns></returns>
DateTime? ConvertToSiteTimeZone(DateTime? dateUtc);
DateTime ConvertFromSiteTimeZone(DateTime dateLocal);
/// <summary>
/// Converts a non-nullable date from the Orchard configured time zone to UTC.
/// </summary>
/// <param name="dateLocal">The non-nullable local date to convert. DateTime.MinValue is translated to null.</param>
/// <returns></returns>
DateTime? ConvertFromSiteTimeZone(DateTime dateLocal);
/// <summary>
/// Converts a nullable date from the Orchard configured time zone to UTC.
/// </summary>
/// <param name="dateLocal">The nullable local date to convert.</param>
/// <returns></returns>
DateTime? ConvertFromSiteTimeZone(DateTime? dateLocal);
///// <summary>
///// Converts a nullable date from the Orchard configured time zone to UTC.
///// </summary>
///// <param name="dateLocal">The nullable local date to convert.</param>
///// <returns></returns>
//DateTime? ConvertFromSiteTimeZone(DateTime? dateLocal);
/// <summary>
/// Converts a date from Gregorian calendar to the Orchard configured calendar.
/// </summary>
/// <param name="date">The Gregorian calendar date to convert.</param>
/// <returns>Null if the supplied date parameter was null. Otherwise a <c>DateTimeParts</c> instance representing the converted date.</returns>
DateTimeParts? ConvertToSiteCalendar(DateTime? date);
/// <returns>A <c>DateTimeParts</c> instance representing the converted date.</returns>
DateTimeParts ConvertToSiteCalendar(DateTime date);
///// <summary>
///// Converts a nullable date from Gregorian calendar to the Orchard configured calendar.
///// </summary>
///// <param name="date">The nullable Gregorian calendar date to convert.</param>
///// <returns>Null if the supplied date parameter was null. Otherwise a <c>DateTimeParts</c> instance representing the converted date.</returns>
//DateTimeParts? ConvertToSiteCalendar(DateTime? date);
/// <summary>
/// Converts a date from the Orchard configured calendar to Gregorian calendar.
/// </summary>
/// <param name="parts">A <c>DateTimeParts</c> instance representing the Orchard configured calendar date to convert.</param>
/// <returns>Null if the supplied parts parameter was null. Otherwise the converted Gregorian calendar date.</returns>
DateTime? ConvertFromSiteCalendar(DateTimeParts? parts);
/// <returns>A <c>DateTime</c> instance representing the converted date.</returns>
DateTime ConvertFromSiteCalendar(DateTimeParts parts);
///// <summary>
///// Converts a nullable date from the Orchard configured calendar to Gregorian calendar.
///// </summary>
///// <param name="parts">A <c>DateTimeParts</c> instance representing the Orchard configured calendar date to convert.</param>
///// <returns>Null if the supplied parts parameter was null. Otherwise a <c>DateTime</c> instance representing the converted date.</returns>
//DateTime? ConvertFromSiteCalendar(DateTimeParts? parts);
/// <summary>
/// Converts a non-nullable date from Gregorian calendar UTC to the Orchard configured calendar and time zone and formats it using the default long date and time format string.
/// Converts a non-nullable UTC date in Gregorian calendar to a localized short date string.
/// </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>
/// <param name="options">An optional <c>DateLocalizationOptions</c> instance used to control various aspects of the conversion process.</param>
/// <returns></returns>
string ConvertToLocalString(DateTime date, string nullText = null);
string ConvertToLocalizedDateString(DateTime date, DateLocalizationOptions options = null);
/// <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.
/// Converts a nullable UTC date in Gregorian calendar to a localized short date string.
/// </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>
/// <param name="options">An optional <c>DateLocalizationOptions</c> instance used to control various aspects of the conversion process.</param>
/// <returns></returns>
string ConvertToLocalString(DateTime? date, string format, string nullText = null);
string ConvertToLocalizedDateString(DateTime? date, DateLocalizationOptions options = 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.
/// Converts a non-nullable UTC date in Gregorian calendar to a localized long time string.
/// </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>
/// <param name="options">An optional <c>DateLocalizationOptions</c> instance used to control various aspects of the conversion process.</param>
/// <returns></returns>
string ConvertToLocalDateString(DateTime date, string nullText = null);
string ConvertToLocalizedTimeString(DateTime date, DateLocalizationOptions options = 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.
/// Converts a nullable UTC date in Gregorian calendar to a localized long time string.
/// </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>
/// <param name="options">An optional <c>DateLocalizationOptions</c> instance used to control various aspects of the conversion process.</param>
/// <returns></returns>
string ConvertToLocalDateString(DateTime? date, string nullText = null);
string ConvertToLocalizedTimeString(DateTime? date, DateLocalizationOptions options = 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.
/// Converts a non-nullable UTC date in Gregorian calendar to a localized short date/time string.
/// </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>
/// <param name="options">An optional <c>DateLocalizationOptions</c> instance used to control various aspects of the conversion process.</param>
/// <returns></returns>
string ConvertToLocalTimeString(DateTime date, string nullText = null);
string ConvertToLocalizedString(DateTime date, DateLocalizationOptions options = 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.
/// Converts a nullable UTC date in Gregorian calendar to a localized short date/time string.
/// </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>
/// <param name="options">An optional <c>DateLocalizationOptions</c> instance used to control various aspects of the conversion process.</param>
/// <returns></returns>
string ConvertToLocalTimeString(DateTime? date, string nullText = null);
string ConvertToLocalizedString(DateTime? date, DateLocalizationOptions options = null);
/// <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.
/// Converts a non-nullable UTC date in Gregorian calendar to a localized string with the specified format.
/// </summary>
/// <param name="dateString">The local date and time string to parse and convert.</param>
/// <param name="date">The non-nullable UTC date to convert. DateTime.MinValue is translated to null.</param>
/// <param name="format">A standard or custom DateTime format string to use when formatting the date.</param>
/// <param name="options">An optional <c>DateLocalizationOptions</c> instance used to control various aspects of the conversion process.</param>
/// <returns></returns>
DateTime? ConvertFromLocalString(string dateString);
string ConvertToLocalizedString(DateTime date, string format, DateLocalizationOptions options = null);
/// <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.
/// Converts a nullable UTC date in Gregorian calendar to a localized string with the specified format.
/// </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>
/// <param name="date">The nullable UTC date to convert.</param>
/// <param name="format">A standard or custom DateTime format string to use when formatting the date.</param>
/// <param name="options">An optional <c>DateLocalizationOptions</c> instance used to control various aspects of the conversion process.</param>
/// <returns></returns>
DateTime? ConvertFromLocalString(string dateString, string timeString);
string ConvertToLocalizedString(DateTime? date, string format, DateLocalizationOptions options = null);
/// <summary>
/// Converts a localized date string to a UTC date in Gregorian calendar.
/// </summary>
/// <param name="dateString">The localized date string to convert.</param>
/// <param name="options">An optional <c>DateLocalizationOptions</c> instance used to control various aspects of the conversion process.</param>
/// <returns>A <c>DateTime</c> instance where the time component equals that of DateTime.MinValue.</returns>
/// <remarks>
/// If the dateString parameter is null or equal to DateLocalizationOptions.NullText property, this method returns null.
/// </remarks>
DateTime? ConvertFromLocalizedDateString(string dateString, DateLocalizationOptions options = null);
/// <summary>
/// Converts a localized time string to a UTC date in Gregorian calendar.
/// </summary>
/// <param name="timeString">The localized time string to convert.</param>
/// <param name="options">An optional <c>DateLocalizationOptions</c> instance used to control various aspects of the conversion process.</param>
/// <returns>A <c>DateTime</c> instance where the date component equals that of DateTime.MinValue.</returns>
/// <remarks>
/// If the timeString parameter is null or equal to DateLocalizationOptions.NullText property, this method returns null.
/// </remarks>
DateTime? ConvertFromLocalizedTimeString(string timeString, DateLocalizationOptions options = null);
/// <summary>
/// Converts separate localized date and time strings to a single UTC date in Gregorian calendar.
/// </summary>
/// <param name="dateString">The localized date/time string to convert.</param>
/// <param name="timeString">The localized time string to convert.</param>
/// <param name="options">An optional <c>DateLocalizationOptions</c> instance used to control various aspects of the conversion process.</param>
/// <returns></returns>
/// <remarks>
/// If the dateString parameter is null or equal to DateLocalizationOptions.NullText property, the returned <c>DateTime</c> instance will have a date component that equals that of DateTime.MinValue.
/// If the timeString parameter is null or equal to DateLocalizationOptions.NullText property, the returned <c>DateTime</c> instance will have a time component that equals that of DateTime.MinValue.
/// If both dateString and timeString parameters are null or equal to DateLocalizationOptions.NullText property, this method returns null.
/// </remarks>
DateTime? ConvertFromLocalizedString(string dateString, string timeString, DateLocalizationOptions options = null);
/// <summary>
/// Converts a localized date/time string to a UTC date in Gregorian calendar.
/// </summary>
/// <param name="dateTimeString">The localized date/time string to convert.</param>
/// <param name="options">An optional <c>DateLocalizationOptions</c> instance used to control various aspects of the conversion process.</param>
/// <returns></returns>
/// <remarks>
/// If the dateTimeString parameter is null or equal to DateLocalizationOptions.NullText property, this method returns null.
/// </remarks>
DateTime? ConvertFromLocalizedString(string dateTimeString, DateLocalizationOptions options = null);
}
}

View File

@@ -43,10 +43,12 @@ struct DateLocalizationOptions {
TODO:
* Test for proper handling of fraction (f) format specifier - suspect it does not work properly in current state
* Add formatting and parsing of time zone information (add timezone properties to TimeParts structure)
* Rewrite DefaultDateLocalizationServices
* Add support for both standard and custom format strings
* Write unit tests for DefaultDateLocalizationServices
* Add warning message when saving unsupported combination in settings
* Add support for the different Gregorian calendar types
* Go over date conversion logic in audit trail filtering to make sure it's correct
* Go over date conversion logic in DateTokens to make sure it's correct
* Improve DateTimeField:
- Surface the field mode (date, time or both)
- Do not perform time-zone conversion in date-only mode

View File

@@ -261,6 +261,7 @@
<Compile Include="FileSystems\Media\FileSystemStorageProvider.cs" />
<Compile Include="FileSystems\Media\IMimeTypeProvider.cs" />
<Compile Include="Indexing\ISearchBits.cs" />
<Compile Include="Localization\Models\DateLocalizationOptions.cs" />
<Compile Include="Localization\Models\DateParts.cs" />
<Compile Include="Localization\Models\DateTimeParts.cs" />
<Compile Include="Localization\Models\TimeParts.cs" />