TimeFormatterService.java
package com.example.time.service;
import com.example.time.exception.InvalidTimeFormatException;
import com.example.time.formatter.SpokenTimeFormatter;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoField;
import java.util.Map;
import org.springframework.stereotype.Component;
/**
* Service for formatting time into spoken language based on locale.
*
* <p>This service uses a map of locale-specific time formatters to convert a time string in HH:mm
* format into a spoken representation.
*/
@Component
public class TimeFormatterService {
private final Map<String, SpokenTimeFormatter> formatterMap;
private static final DateTimeFormatter TIME_FORMATTER =
new DateTimeFormatterBuilder()
.appendValue(ChronoField.HOUR_OF_DAY, 1, 2, java.time.format.SignStyle.NOT_NEGATIVE)
.appendPattern(":mm")
.toFormatter();
public TimeFormatterService(Map<String, SpokenTimeFormatter> formatterMap) {
this.formatterMap = formatterMap;
}
public String format(String timeStr, String locale) throws InvalidTimeFormatException {
try {
final SpokenTimeFormatter formatter =
formatterMap.get(locale.toLowerCase(java.util.Locale.ROOT));
if (formatter == null) {
throw new InvalidTimeFormatException("Unknown locale: " + locale);
}
return formatter.format(LocalTime.parse(timeStr, TIME_FORMATTER));
} catch (DateTimeParseException e) {
throw new InvalidTimeFormatException("Invalid time format. Use HH:mm (e.g. 07:30).", e);
} catch (Exception e) {
throw new InvalidTimeFormatException("Error formatting time: " + e.getMessage(), e);
}
}
}