Tip - 'local_date' filter to always convert a datetime to configured TimeZone
Closed this issue · 1 comments
nicholas-brooks commented
My use-case was to always convert a ISO8601+time-offset datetime string into the configured TemplateContext.TimeZone property.
So to do so, I created a 'local_date' filter that does exactly that:
internal static class FluidFilters
{
public static ValueTask<FluidValue> LocalDateFilter(FluidValue input, FilterArguments arguments, TemplateContext context)
{
var value = TimeZoneConverter(input, context);
return ReferenceEquals(value, NilValue.Instance) ? value : MiscFilters.Date(value, arguments, context);
}
private static FluidValue TimeZoneConverter(FluidValue input, TemplateContext context)
{
if (!input.TryGetDateTimeInput(context, out var value))
{
return NilValue.Instance;
}
var result = TimeZoneInfo.ConvertTime(value, context.TimeZone);
return new DateTimeValue(result);
}
}
And code to use the above:
[Theory]
[InlineData("2022-12-07T22:22:18.1234-05:00")]
[InlineData("2022-12-08T03:22:18.1234+00:00")]
[InlineData("2022-12-08T05:22:18.1234+02:00")]
[InlineData("2022-12-08T13:52:18.1234+10:30")]
public void local_date_filter_should_convert_ISO8601_plus_offset_to_time_for_configured_TimeZone(
string timestamp)
{
var templateOptions = new TemplateOptions
{
TimeZone = TimeZoneInfo.FindSystemTimeZoneById("Indian/Maldives"),
};
templateOptions.Filters.AddFilter("local_date", FluidFilters.LocalDateFilter);
var parser = new FluidParser();
var template = parser.Parse(@"Published at: {{ PublishedAt | local_date: ""%e %b %y %r"" }}");
var result = template.Render(new TemplateContext(new {PublishedAt = timestamp}, templateOptions));
Assert.Equal("Published at: 8 Dec 22 08:22:18 AM", result);
}
Originally posted by @nicholas-brooks in #537 (comment)
sebastienros commented
I think that's a sensible request. I'd rather have this filter related to timezones though (instead of dates), and use the standard | date: ...
filter for formatting. That isolates this Fluid specific feature in the same way as it does for timezones.
One option could be with a special timezone name, like {{ now | date | time_zone: 'local' }}
This would not require an extra filter.