6

I'm faced with the issue that I need to convert time from 24 format to AM/PM format (and vice-versa) removing redundant values such as nanoseconds and seconds by time4j library.

I'm using the time4j library because Java can't handle Windows Time Zones and I have to convert them via time4j

Conversion from 24 hour format to AM/PM will depend on users localization. And I want to transmit it (localization) as an argument. Localization will look like "en-US" string.

For example: If users localization is "en-US" then convert 24 hour format to AM/PM. Else keep current value.

Or maybe it's better to get time in the format I need when I already define localization of my user?

Any ideas how to do this? Please help)

I have to spend a lot of time reading time4j doc but my mind is blown

To have full scale of what I'm doing and what the purpose all of this:

I have to get users timeZone from my DB which corresponds to Windows Time Zones and convert them to IANA time zones. I already did this by this method

WindowsZone wzn = WindowsZone.of(userTimeZoneId); //userTimeZoneId="eg. FLE Standart Time"
TZID winZone = wzn.resolveSmart(new Locale("","001"));
System.out.println(winZone.canonical()); // WINDOWS~Europe/Kiev

Where "userTimeZoneId" is timeZone from DB. It corresponds to Microsoft Name of Time Zones

My next step is to get time / or time stamp from users time zone which I already convert to IANA time zones.

I did like this:

PlainTime currentTime = SystemClock.inZonalView(winZone).now().toTime(); 
//currentTime: "T17:31:37,057"

Where "winZone" converted timeZone (eg. "WINDOWS~Europe/Kiev")

So now returning to my problem I described at the top of the post.

  1. Maybe it's better to get time in the format I need when I already define localization of my user?

  2. How can I convert time from 24 format to AM/PM and vise-versa?

  3. How to remove redundant values such as nanoseconds and seconds?

  4. How can I use user localization in conversion?

David M. Karr
  • 11,418
  • 13
  • 71
  • 144
  • Possible duplicate of [Converting XX:XX AM/PM to 24 Hour Clock](https://stackoverflow.com/questions/23316089/converting-xxxx-am-pm-to-24-hour-clock) – StatelessDev Jun 15 '18 at 12:25
  • 1
    Why not use Java's LocalDateTime? – Sedrick Jun 15 '18 at 13:29
  • 1
    Because Java's LocalDateTime can't handle with Windows Time Zones. That's why I have to use time4j library. If there any possibility to resolve my issue using Java LocalDateTime - i will be really grateful – Roman Shabanov Jun 15 '18 at 13:47

1 Answers1

3

This is straight forward as long as you know that the dedicated formatter API in Time4J is based on ChronoFormatter:

Locale ukraine = new Locale("en", "UA"); // or use new Locale("en", "001") for worldwide
TZID winZone = WindowsZone.of("FLE Standard Time").resolveSmart(ukraine);
PlainTime currentTime = SystemClock.inZonalView(winZone).now().toTime();
System.out.println(currentTime); // T12:02:40,344

// truncate seconds and nanoseconds
currentTime = currentTime.with(PlainTime.PRECISION, ClockUnit.MINUTES);
System.out.println(currentTime); // T12:02

// format in am/pm-notation
ChronoFormatter<PlainTime> f1 =
    ChronoFormatter.ofTimePattern("h:mm a", PatternType.CLDR, Locale.US);
String formatted1 = f1.format(currentTime);
System.out.println(formatted1); // 12:02 pm

// or use styled formatter (which has only limited control over displayed precision)
ChronoFormatter<PlainTime> f2 = 
    ChronoFormatter.ofTimeStyle(DisplayMode.SHORT, Locale.US);
String formatted2 = f2.format(currentTime);
System.out.println(formatted2); // 12:02 pm

A style-based solution (as demonstrated above for Time4J) is appropriate if you want to let the locale control the format pattern. For example, a german locale would print "12:02" instead of "12:02 pm" (US).

By the way, you are also free to use the format-API of java.time if you want because PlainTime implements the JSR-310-interface TemporalAccessor:

DateTimeFormatter dtf = DateTimeFormatter.ofPattern("h:mm a", Locale.US);
System.out.println(dtf.format(currentTime)); // 12:02 PM

Here the different capitalization originates from the fact that the JDK (at least on my system) still uses older CLDR-data for internationalization while Time4J has its own resources based on actual CLDR-version v33. A future Java version will surely change the capitalization. In general, I still recommend to use ChronoFormatter for sake of more features, better i18n and more performance. For example, the reverse way of parsing am/pm-literals is more reliable using Time4J than in java.time if you work with different locales.

If you like to use "AM" and "PM" in capitalized letters (or any other customized format) together with ChronoFormatter then you can also use:

Map<Meridiem, String> map = new EnumMap<>(Meridiem.class);
map.put(Meridiem.AM, "AM");
map.put(Meridiem.PM, "PM");
ChronoFormatter<PlainTime> f3 =
    ChronoFormatter
        .setUp(PlainTime.axis(), Locale.ROOT)
        .addPattern("h:mm ", PatternType.CLDR)
        .addText(PlainTime.AM_PM_OF_DAY, map)
        .build();
String formatted3 = f3.format(currentTime);
System.out.println(formatted3); // 12:02 PM
Meno Hochschild
  • 38,305
  • 7
  • 88
  • 115
  • Thank you man! You really help me) It's working! Small modifications and adaptation will help me make methods more flexible) – Roman Shabanov Jun 18 '18 at 14:54