chiark / gitweb /
TOML::Tiny::Faithful: Provide own DateTime formatter
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Wed, 6 May 2020 00:06:07 +0000 (01:06 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Wed, 6 May 2020 00:18:28 +0000 (01:18 +0100)
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
lib/TOML/Tiny/Faithful.pm

index 414a2127076a47e48bc3e0c461a80f3b6e1987bc..5388c769dcb75f48a1b313e9dc5995084148b4ca 100644 (file)
--- 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';
index 58512003c1a1492bf95674746e9c4447aebfe3ab..42edf1bdba42947fbf6d429d84d6e42bb4e9dc1b 100644 (file)
@@ -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