I was trying to progress with FREEMARKER-35. So we have settings akin to the good old data_format/datatime_format/time_format, but they are named after the java.time temporal classes, like zoned_date_time_format, local_date_time_format, etc. The setting value is a pattern as defined by java.time.format.DateTimeFormatter, like "uuuu-MM-dd HH:mm". (Actually it can also have other kind of values, like "medium", "iso", etc. but for now it doesn't matter.)
Problem 1: When the zone is not shown If a DateTimeFormatter doesn't show the time zone (or the offset), it of course still will not convert it to the current time zone (dictated by the FreeMarker time_zone setting). So if I have ZonedDateTime 2000-01-01 15:00+05, and the current time_zone is +02, and the format doesn't contain a time zone part, you just see "2000-01-01 15:00", and not "2000-01-01 12:00". That's unlike with java.util.Date, where no such accident can happen; if you see no time zone, then you see the local date-time in the current time zone. But unlike java.util.Date, ZonedDateTime doesn't store an instant of time, instead it stores a local date-time and a zone. So I'm not supposed to mess with that zone, just show it as is. But on the same time, I can't tell if the DateTimeFormatter will actually show the zone (I don't see an API to query that). Worse, typical local default formats like "MEDIUM" and "SHORT", do not contain time zone (checked on Java 8 and 13, with a dozen of locales). So users will burn themselves with this, showing misleading information. Proposed solution: When a new format is provided to FreeMarker, it will detect if the output of that format is affected by the zone (or offset) of the input temporal, by providing two dummy inputs that only differ in time zone, and see if the outputs differ. That's admittedly a dirty hack (and bit of runtime overhead), but I see no API to query such information about a DateTimeFormatter. If I have found that the zone (or offset) is not shown, they I will convert the input temporals to the current time zone as part of the formatting. Otherwise, don't do time zone conversion, and so the zone will be shown as is. So we deviate from what java.time does, but hopefully do what's safest, and practical. Problem 2: Default formats are failing for some input types It's about DateTimeFormatter.ofLocalizedXxx(FormatStyle), where FormatStyle can be FULL, LONG, MEDIUM, and SHORT. The goal of this API is give the default formatter for given locale, each my uses a different pattern internally. The problem is that the provided formatters only works reliably for ZonedDateTime and LocalDate, but not for LocalDateTime, OffsetDateTime, or OffsetTime, because the localized pattern my displays the time zone, even if your input type has no such field! So if you try to format a LocalDateTime with LONG, you get an exception with an otherwise quite unhelpful error message. So how to shield the users from this? Based on a dozen of locales and Java 8 and 13, it seems that MEDIUM and SHORT never contains zone, so they are safe, while FULL and LONG always do. Although, it's just an observation, I see no such promise in the API. Luckily, our default format will be MEDIUM, as that's the default for java.util.Date too. (That's also why Problem 1 has a big impact.) So we are kind of fine there... hoping that they won't add time zone to the MEDIUM format of some locale in the future. Other than that, I don't know what to do if someone uses LONG format for example. I think adding and displaying zones to temporals that are not zoned by their very nature (LocalDateTime, etc.), is not acceptable. We had one job after all: showing data, without distortion. We don't know if that LocalDateTime or LocalTime is the instant in a given time zone, that we would show, if we add the current time zone to it. There's also the wild possibility of somehow editing the zone out of the format given, but I don't see how, as I can't even get hold of the pattern of the DateTimeFormatter returned by DateTimeFormatter.ofLocalizedXxx. So, for now, I plan to let it fail, except I will try if it still fails if I have zone, and if it doesn't, then tell the user in the error message that this format only works for inputs that contains a time zone. We will have to add some built-in to explicitly add a time zone to local stuff. Anybody has some other ideas, or wants me to not do some of these, please tell it! -- Best regards, Daniel Dekany