How to parse HH: mm into the number of minutes, taking into account the locale's time separator?
I have an input string of the format "HH: mm" where the time separator matches the language setting (for example, "10: 45" for USA or "10.45" for Italy). I need to convert it to a number of minutes.
This is what I came up with:
String timeSeparator = getTimeSeparator(locale);
String[] duration = durationString.split(Pattern.quote(timeSeparator));
int minutes = Integer.valueOf(duration[0])*60 + Integer.valueOf(duration[1]);
getTimeSeparator
method taken from stackoverflow question/1043525 / ...
Is there an easier way? For example using `java.time '.
source to share
In Java 8 you can use DateTimeFormatter.ofLocalizedTime
to get the date and time format. Then you can use it to parse the string intoLocalTime
and extract the minute field .
public static int getMinute(String timeString, Locale locale) {
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT)
.withLocale(locale);
LocalTime time = LocalTime.parse(timeString, formatter);
return time.getHour()*60 + time.getMinute();
}
Example:
System.out.println(getMinute("10.47", new Locale("fi"))); // 647
System.out.println(getMinute("11:23", Locale.ROOT)); // 683
If you don't need a time separator, we could use a fixed pattern.
public static int getMinute(String timeString, Locale locale) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH[:][.]mm", locale);
LocalTime time = LocalTime.parse(timeString, formatter);
return time.getHour()*60 + time.getMinute();
}
( […]
Is optional, so it will fit HH:mm
, HH.mm
, HHmm
and HH:.mm
)
source to share
TL; DR
Duration.parse(
"PT" +
"10:45".replace( ":" , "M" )
.replace( "-" , "M" )
.replace( "." , "M" )
.replace( "," , "M" )
+ "S"
).toMinutes()
"10:45" → PT10M45S → 10
ISO 8601 format
The ISO 8601 standard defines the format for such time intervals that are not tied to the timeline:PnYnMnDTnHnMnS
The icon P
indicates the beginning. T
separates any years-months-days from hours-minutes-seconds. So, an hour and a half - PT1H30M
. Your example is ten minutes and forty-five seconds PT10M45S
.
Perform simple string manipulation to convert your input to this format.
String input = "10:45" ;
String inputStandardized = "PT" +
input.replace( ":" , "M" )
.replace( "-" , "M" )
.replace( "." , "M" )
.replace( "," , "M" )
+ "S" ;
PT10M45S
Duration
Disassemble how Duration
. The java.time classes use ISO 8601 formats by default when parsing and generating strings. Therefore, there is no need to specify a formatting template.
Duration duration = Duration.parse( inputStandardized );
duration.toString (): PT10M45S
You can use an object Duration
to do date and time math by going to plus
and minus
. Thus, you may not need the minutes as an integer. But you can set the total number of minutes in the duration.
long minutes = duration.toMinutes();
ten
See this code run at IdeOne.com .
Council. Using the clock format over a period of time is problematic. Ambiguity leads to confusion and errors. I suggest using the ISO 8601 standard formats for durations as they are designed to be unambiguous, easy to read, and easy to parse.
source to share
Notice very elegant, but it will get the job done
String pattern = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT)
.withLocale(locale).format(LocalTime.MIN)
.replaceFirst("\\d*", "H").replaceFirst("\\d.*", "mm");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern, locale);
int minutes = formatter.parse(string).get(ChronoField.MINUTE_OF_DAY);
source to share
You can use the method getLocalizedDateTimePattern
to get a template with which to initialize DateTimeFormatter
to parse the time with a given language. The first one null
refers to a date that you don't need in your case.
String timePattern = DateTimeFormatterBuilder.getLocalizedDateTimePattern(
null, FormatStyle.SHORT, IsoChronology.INSTANCE, locale);
Then you use it to create the formatting (note that you need to specify the locale again):
DateTimeFormatter dtf = DateTimeFormatter.ofPattern(timePattern, locale);
If, instead of formatting SHORT
for, locale
you expect "HHcmm"
where 'c'
is a non-numeric char that is the time separator for that locale
, then either:
-
extract numbers from text
String[] duration = durationString.split("\\D"); int minutes = parseInt(duration[0])*60 + parseInt(duration[1]);
-
do
DateTimeFormatter
with time separatorDateTimeFormatter dtf = DateTimeFormatter.ofPattern( String.format("HH%smm", timeSeparator), locale); LocalTime time = LocalTime.parse(text, dtf); int minutes = time.toSecondOfDay() / 60;
or if you should
int minutes = ChronoUnit.MINUTES.between(LocalTime.MIN, time);
source to share
First analyze the time of the instance LocalTime
, then calculate the difference at the start of the day with Duration
:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendLocalized(null, FormatStyle.SHORT)
.toFormatter(Locale.ITALY);
LocalTime time = LocalTime.from(formatter.parse("10.45"));
long minutes = Duration.between(LocalTime.MIN, time).toMinutes();
higher results up to 645
source to share