schultek / dart_mappable

Improved json serialization and data classes with full support for generics, inheritance, customization and more.
https://pub.dev/packages/dart_mappable
MIT License
135 stars 20 forks source link

DateTime serializes to UTC by default... good, but then how to deserialize back to local time zone? #206

Open tgrushka opened 1 week ago

tgrushka commented 1 week ago

Hi @schultek, thanks for the package! In #125, you explained that: "The default mapper for DateTime transforms it to UTC when encoded, so that there is no problem when the value is passed to some other program in a different local timezone." This is great, because that's how most databases store DateTimes as well.

However, I noticed when deserializing, the resulting DateTime object is still in UTC. You also explained that: "Fyi be aware that you always can make your own mapper for DateTime and use it globally for all DateTime fields, if that helps." OK, so I will do that by copying and modifying DateTimeMapper and using MapperContainer.globals.use(LocalDateTimeMapper()); as the docs suggest.

IMHO, it might be good to do something like this (convert back to local if encoding mode was to UTC):

  @override
  DateTime decode(dynamic value) {
    final dateTime = switch(value) {
      String value => DateTime.parse(value),
      num value => DateTime.fromMillisecondsSinceEpoch(value.round()),
      _ => throw MapperException.unexpectedType(value.runtimeType, 'String or num'),
    };
    return switch (encodingMode) {
      DateTimeEncoding.iso8601String => dateTime,
      DateTimeEncoding.utcIso8601String => dateTime.toLocal(),
      DateTimeEncoding.millisSinceEpoc => dateTime,
    };
  }

I think it might be less surprising to users of this package if this were the default behavior, as I used a date picker in my app, then on refresh (restore from JSON) it was switching to UTC and I realized it was in the mapper. Of course, another DateTimeEncoding value could be added, i.e. DateTimeEncoding.localUtcIso8601String... Maybe/maybe not...

What do you think?

schultek commented 4 days ago

How about adding a DateTimeDecoding value to choose from e.g. "unchanged", "asUtc" and "asLocal".

Then its independent of the encoding, ans also not a breaking change.