From 0f068c57d1d75428c98592019090351ce239ce8d Mon Sep 17 00:00:00 2001 From: Matt Sanders Date: Fri, 17 Dec 2021 14:49:19 -0800 Subject: [PATCH 1/2] Changed TryGetDateTimeInput from private to public and changed to be an extension method. --- Fluid/Filters/MiscFilters.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Fluid/Filters/MiscFilters.cs b/Fluid/Filters/MiscFilters.cs index 5853023f..04e8b24b 100644 --- a/Fluid/Filters/MiscFilters.cs +++ b/Fluid/Filters/MiscFilters.cs @@ -264,7 +264,7 @@ public static ValueTask EscapeOnce(FluidValue input, FilterArguments public static ValueTask ChangeTimeZone(FluidValue input, FilterArguments arguments, TemplateContext context) { - if (!TryGetDateTimeInput(input, context, out var value)) + if (!input.TryGetDateTimeInput(context, out var value)) { return NilValue.Instance; } @@ -285,7 +285,7 @@ public static ValueTask ChangeTimeZone(FluidValue input, FilterArgum public static ValueTask Date(FluidValue input, FilterArguments arguments, TemplateContext context) { - if (!TryGetDateTimeInput(input, context, out var value)) + if (!input.TryGetDateTimeInput(context, out var value)) { return NilValue.Instance; } @@ -520,7 +520,7 @@ void ForStrf(DateTimeOffset value, string format, StringBuilder result) public static ValueTask FormatDate(FluidValue input, FilterArguments arguments, TemplateContext context) { - if (!TryGetDateTimeInput(input, context, out var value)) + if (!input.TryGetDateTimeInput(context, out var value)) { return NilValue.Instance; } @@ -542,7 +542,7 @@ public static ValueTask FormatDate(FluidValue input, FilterArguments return new StringValue(value.ToString(format, culture)); } - private static bool TryGetDateTimeInput(FluidValue input, TemplateContext context, out DateTimeOffset result) + public static bool TryGetDateTimeInput(this FluidValue input, TemplateContext context, out DateTimeOffset result) { result = context.Now(); From 5785c9246901e1af77906429ee7736459b47ee3e Mon Sep 17 00:00:00 2001 From: Matt Sanders Date: Fri, 17 Dec 2021 18:57:54 -0800 Subject: [PATCH 2/2] Moved TryGetDateTimeInput extension into the FluidValueExtensions class along with the private static values it depends on. --- Fluid/Filters/MiscFilters.cs | 118 -------------------------- Fluid/Values/FluidValueExtensions.cs | 121 ++++++++++++++++++++++++++- 2 files changed, 120 insertions(+), 119 deletions(-) diff --git a/Fluid/Filters/MiscFilters.cs b/Fluid/Filters/MiscFilters.cs index 04e8b24b..442f4b6c 100644 --- a/Fluid/Filters/MiscFilters.cs +++ b/Fluid/Filters/MiscFilters.cs @@ -9,61 +9,18 @@ using System.Threading.Tasks; using System.Text; using System.IO; -using System.Linq; using System.Reflection; namespace Fluid.Filters { public static class MiscFilters { - private static readonly string[] DefaultFormats = { - "yyyy-MM-ddTHH:mm:ss.FFF", - "yyyy-MM-ddTHH:mm:ss", - "yyyy-MM-ddTHH:mm", - "yyyy-MM-dd", - "yyyy-MM", - "yyyy" - }; - - private static readonly string[] SecondaryFormats = { - // Formats used in DatePrototype toString methods - "ddd MMM dd yyyy HH:mm:ss 'GMT'K", - "ddd MMM dd yyyy", - "HH:mm:ss 'GMT'K", - - // standard formats - "yyyy-M-dTH:m:s.FFFK", - "yyyy/M/dTH:m:s.FFFK", - "yyyy-M-dTH:m:sK", - "yyyy/M/dTH:m:sK", - "yyyy-M-dTH:mK", - "yyyy/M/dTH:mK", - "yyyy-M-d H:m:s.FFFK", - "yyyy/M/d H:m:s.FFFK", - "yyyy-M-d H:m:sK", - "yyyy/M/d H:m:sK", - "yyyy-M-d H:mK", - "yyyy/M/d H:mK", - "yyyy-M-dK", - "yyyy/M/dK", - "yyyy-MK", - "yyyy/MK", - "yyyyK", - "THH:mm:ss.FFFK", - "THH:mm:ssK", - "THH:mmK", - "THHK" - }; - private static readonly Regex HtmlCaseRegex = new Regex( "(? FormatDate(FluidValue input, FilterArguments return new StringValue(value.ToString(format, culture)); } - public static bool TryGetDateTimeInput(this FluidValue input, TemplateContext context, out DateTimeOffset result) - { - result = context.Now(); - - if (input.Type == FluidValues.String) - { - var stringValue = input.ToStringValue(); - - if (stringValue == Now || stringValue == Today) - { - return true; - } - else - { - var success = true; - - if (!DateTime.TryParseExact(stringValue, DefaultFormats, context.CultureInfo, DateTimeStyles.None, out var dateTime)) - { - if (!DateTime.TryParseExact(stringValue, SecondaryFormats, context.CultureInfo, DateTimeStyles.None, out dateTime)) - { - if (!DateTime.TryParse(stringValue, context.CultureInfo, DateTimeStyles.None, out dateTime)) - { - if (!DateTime.TryParse(stringValue, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime)) - { - success = false; - } - } - } - } - - // If no timezone is specified, assume local using the configured timezone - if (success) - { - if (dateTime.Kind == DateTimeKind.Unspecified) - { - result = new DateTimeOffset(dateTime, context.TimeZone.GetUtcOffset(dateTime)); - } - else - { - result = new DateTimeOffset(dateTime); - } - } - - return success; - } - } - else if (input.Type == FluidValues.Number) - { - var dateTime = DateTimeOffset.FromUnixTimeSeconds((long)input.ToNumberValue()); - result = dateTime.ToOffset(context.TimeZone.GetUtcOffset(dateTime)); - } - else if (input.Type == FluidValues.DateTime) - { - result = (DateTimeOffset)input.ToObjectValue(); - } - else - { - switch (input.ToObjectValue()) - { - case DateTime dateTime: - result = dateTime; - break; - - case DateTimeOffset dateTimeOffset: - result = dateTimeOffset; - break; - - default: - return false; - } - } - - return true; - } - private static async ValueTask WriteJson(Utf8JsonWriter writer, FluidValue input, TemplateContext ctx, HashSet stack = null) { switch (input.Type) diff --git a/Fluid/Values/FluidValueExtensions.cs b/Fluid/Values/FluidValueExtensions.cs index 114627ca..ed16be5e 100644 --- a/Fluid/Values/FluidValueExtensions.cs +++ b/Fluid/Values/FluidValueExtensions.cs @@ -1,7 +1,126 @@ -namespace Fluid.Values +using System; +using System.Globalization; + +namespace Fluid.Values { public static class FluidValueExtensions { + private const string Now = "now"; + private const string Today = "today"; + + private static readonly string[] DefaultFormats = { + "yyyy-MM-ddTHH:mm:ss.FFF", + "yyyy-MM-ddTHH:mm:ss", + "yyyy-MM-ddTHH:mm", + "yyyy-MM-dd", + "yyyy-MM", + "yyyy" + }; + + private static readonly string[] SecondaryFormats = { + // Formats used in DatePrototype toString methods + "ddd MMM dd yyyy HH:mm:ss 'GMT'K", + "ddd MMM dd yyyy", + "HH:mm:ss 'GMT'K", + + // standard formats + "yyyy-M-dTH:m:s.FFFK", + "yyyy/M/dTH:m:s.FFFK", + "yyyy-M-dTH:m:sK", + "yyyy/M/dTH:m:sK", + "yyyy-M-dTH:mK", + "yyyy/M/dTH:mK", + "yyyy-M-d H:m:s.FFFK", + "yyyy/M/d H:m:s.FFFK", + "yyyy-M-d H:m:sK", + "yyyy/M/d H:m:sK", + "yyyy-M-d H:mK", + "yyyy/M/d H:mK", + "yyyy-M-dK", + "yyyy/M/dK", + "yyyy-MK", + "yyyy/MK", + "yyyyK", + "THH:mm:ss.FFFK", + "THH:mm:ssK", + "THH:mmK", + "THHK" + }; + + public static bool TryGetDateTimeInput(this FluidValue input, TemplateContext context, out DateTimeOffset result) + { + result = context.Now(); + + if (input.Type == FluidValues.String) + { + var stringValue = input.ToStringValue(); + + if (stringValue == Now || stringValue == Today) + { + return true; + } + else + { + var success = true; + + if (!DateTime.TryParseExact(stringValue, DefaultFormats, context.CultureInfo, DateTimeStyles.None, out var dateTime)) + { + if (!DateTime.TryParseExact(stringValue, SecondaryFormats, context.CultureInfo, DateTimeStyles.None, out dateTime)) + { + if (!DateTime.TryParse(stringValue, context.CultureInfo, DateTimeStyles.None, out dateTime)) + { + if (!DateTime.TryParse(stringValue, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime)) + { + success = false; + } + } + } + } + + // If no timezone is specified, assume local using the configured timezone + if (success) + { + if (dateTime.Kind == DateTimeKind.Unspecified) + { + result = new DateTimeOffset(dateTime, context.TimeZone.GetUtcOffset(dateTime)); + } + else + { + result = new DateTimeOffset(dateTime); + } + } + + return success; + } + } + else if (input.Type == FluidValues.Number) + { + var dateTime = DateTimeOffset.FromUnixTimeSeconds((long)input.ToNumberValue()); + result = dateTime.ToOffset(context.TimeZone.GetUtcOffset(dateTime)); + } + else if (input.Type == FluidValues.DateTime) + { + result = (DateTimeOffset)input.ToObjectValue(); + } + else + { + switch (input.ToObjectValue()) + { + case DateTime dateTime: + result = dateTime; + break; + + case DateTimeOffset dateTimeOffset: + result = dateTimeOffset; + break; + + default: + return false; + } + } + + return true; + } public static FluidValue Or(this FluidValue self, FluidValue other) {