1

I'm using ibm's MessageFormat library to localize an incoming date.

The task here is to run a few checks on the date before showing it to the end user. I get a ZonedDateTime object and I need to make sure that it doesn't fall in the weekend, which I do using the getDayOfWeek.

My problem happens when I try to convert my date to a string using MessageFormat. Since MessageFormat accepts only java.util.Date objects, I convert my ZonedDateTime -> Instant -> Date. Unfortunately, this method results in my "Monday" becoming a "Sunday," as shown below.

I noticed that this "loss" happens upon the Date conversion. This is because the Date.toString() object is being invoked by MessageFormat, and the former uses the JVM's default timezone (in my case, PST). As a result, my UTC gets implicitly converted to a PST and I lose a day.

Any ideas how to tackle this? Is there anything else that I can pass to MessageFormat? Is there a way to use Date but not get this undesired behavior? Is there another localization library I can use?

Breakpoint when debugging shows the undesired behavior

Abdo Salem
  • 51
  • 8
  • The date itself is correct. It is just printing it in PST because the `toString()` method of `Date` class will print it using the local time zone. – Hari Menon Jun 23 '20 at 05:27
  • @HariMenon right, but this means that my end user sees a "Sunday" instead of a "Monday" because MessageFormat will use the converted date. I'm basically always losing a day in this implicit conversion. – Abdo Salem Jun 23 '20 at 05:29
  • 1
    https://stackoverflow.com/q/11610802/829571 - apply the required timezone to the underlying SimpleDateFormats. – assylias Jun 23 '20 at 05:39
  • I don't think Date allows you to do that. Looking at MessageFormatter doc, it looks like you can specify format string to format it as per your wish, like the argStyleText which can accept any SimpleDateFormat. So may be you can change your formatter's format string – Hari Menon Jun 23 '20 at 05:42
  • @HariMenon I think passing an an argStyleText will result in MessageFormatter also passing it to its underlying SimpleDateFormat. The problem here is that this underlying SimpleDateFormat will not use the timezone I want. What I really want is to set the timezone on that SimpleDateFormat. assylias 's suggestion looks good, but it's too wordy to keep looping through all the SimpleDateFormat's in MessageFormat, esp when it's recommended to instantiate a new one everytime. My best option right now is to just use SimpleDateFormats directly. Let me see if it offers the localizations I want. – Abdo Salem Jun 23 '20 at 05:48

1 Answers1

0

Internally, MessageFormat uses a DateFormat object but does not allow you to set its timezone. @Assylias linked a question where the answer tries to pull out the internal DateFormat, set its timezone, and then use the MessageFormat as usual, which resolves the issue.

However, I found that to be too wordy, particularly because you have to create a new MessageFormat everytime (as opposed to reusing the MessageFormat that you already set the timezone for).

What I opted for was to simply use SimpleDateFormat directly.

// I have a ZonedDateTime zonedDateTime that I want to print out.
final SimpleDateFormat dateFormat = new SimpleDateFormat("EEEE, MM dd", locale);
dateFormat.setTimeZone(TimeZone.getTimeZone(zonedDateTime.getZone()));
final String formattedDateString = dateFormat.format(Date.from(zonedDateTime.toInstant()));

I then use String.format to insert my formatted date into a larger string. Hope this helps.

Abdo Salem
  • 51
  • 8
  • 1
    If you are formatting the date manually, why don't you use a DateTimeFormatter? No more timezone conversion required. `String formatted = DateTimeFormatter.ofPattern("EEEE, MM, dd", Locale.UK).format(zonedDateTime)` – assylias Jun 23 '20 at 07:00