From f4110adc48067c3be4d5a389f4c8a92ba09c9395 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Wed, 6 May 2020 01:06:07 +0100 Subject: [PATCH] TOML::Tiny::Faithful: Provide own DateTime formatter We want to preserve the ns and also preserve whether there was a timezone. This is a bit of a mess! Currently this commit only changes things for the case where the DateTime object didn't come from Faithful parser, because Faithful uses RFC3339 which always demands a timezone. --- cpanfile | 1 + lib/TOML/Tiny/Faithful.pm | 26 +++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/cpanfile b/cpanfile index 414a212..5388c76 100644 --- a/cpanfile +++ b/cpanfile @@ -10,6 +10,7 @@ recommends 'Types::Serialiser' => 0; on test => sub{ requires 'Data::Dumper' => '0'; requires 'DateTime::Format::RFC3339' => '0'; + requires 'DateTime::Format::ISO8601' => '0'; requires 'Types::Serialiser' => '0'; requires 'Math::BigInt' => '>= 1.999718'; requires 'TOML::Parser' => '0'; diff --git a/lib/TOML/Tiny/Faithful.pm b/lib/TOML/Tiny/Faithful.pm index 5851200..42edf1b 100644 --- a/lib/TOML/Tiny/Faithful.pm +++ b/lib/TOML/Tiny/Faithful.pm @@ -24,7 +24,7 @@ sub _options { }, inflate_float => sub { 0. + shift; }, no_string_guessing => 1, - datetime_formatter => DateTime::Format::RFC3339->new(), + datetime_formatter => TOML::Tiny::Faithful::DateTime::Formatter->new(), } sub new { @@ -40,6 +40,30 @@ sub to_toml { TOML::Tiny::to_toml($source, _options(), @_); } +package TOML::Tiny::Faithful::DateTime::Formatter; +use DateTime::Format::RFC3339; + +our $base = DateTime::Format::RFC3339->new(); + +sub new ($) { + my ($class) = @_; + bless { }, $class; +} + +sub format_datetime { + my ($self,$dt) = @_; + # RFC3339 always prints a timezone. This is correct for RFC3339 + # but in our application we sometimes have "local datetime"s + # where the time_zone is DateTime::TimeZone::Floating. + # We could use ISO8601 but it never prints the nanoseconds. + # It is easier to strip the timezone offset than add the ns. + my $r = DateTime::Format::RFC3339->new()->format_datetime($dt); + if ((ref $dt->time_zone()) =~ m/Floating/) { + $r =~ s/\+[0-9:.]+$//; + } + $r +} + 1; =head1 SYNOPSIS -- 2.30.2