【问题标题】:How to parse HH:mm into amount of minutes considering locale time separator?考虑到语言环境时间分隔符,如何将 HH:mm 解析为分钟数?
【发布时间】:2017-03-23 18:15:22
【问题描述】:

我有一个“HH:mm”格式的输入字符串,其中时间分隔符根据区域设置(例如,美国的“10:45”或意大利的“10.45”)。我需要将其转换为分钟数。

这是我想出的:

String timeSeparator = getTimeSeparator(locale);
String[] duration = durationString.split(Pattern.quote(timeSeparator));
int minutes = Integer.valueOf(duration[0])*60 + Integer.valueOf(duration[1]);

getTimeSeparator方法取自https://stackoverflow.com/a/7612009/7753225

有没有更简单的方法?例如使用 `java.time'。

【问题讨论】:

  • 您可以删除 Integer.valueOf() 因为您甚至没有使用 Integer,(即使那样,它也会被自动装箱)。我认为 JodaTime 有这个选项。从日期时间获取分钟/秒/无论什么
  • 为什么不忽略分隔符呢? int minutes = Integer.parseInt(durationString.substring(0, 2)) * 60 + Integer.parseInt(durationString.substring(3))

标签: java time java-8 locale separator


【解决方案1】:

tl;博士

Duration.parse( 
    "PT" + 
    "10:45".replace( ":" , "M" )
           .replace( "-" , "M" )
           .replace( "." , "M" )
           .replace( "," , "M" )
    + "S" 
).toMinutes()

“10:45”→PT10M45S→10

ISO 8601 格式

ISO 8601 标准为未附加到时间线的此类时间跨度定义了一种格式:PnYnMnDTnHnMnS

P 标志着开始。 T 将任何年-月-日与小时-分钟-秒分开。所以一个半小时是PT1H30M。你的十分四十五秒的例子是PT10M45S

执行简单的字符串操作,将您的输入转换为这种格式。

String input = "10:45" ;
String inputStandardized = "PT" + 
    input.replace( ":" , "M" )
         .replace( "-" , "M" )
         .replace( "." , "M" )
         .replace( "," , "M" )
         + "S" ;

PT10M45S

Duration

解析为Duration。 java.time 类在解析和生成字符串时默认使用ISO 8601 格式。所以不需要指定格式模式。

Duration duration = Duration.parse( inputStandardized );

duration.toString(): PT10M45S

您可以使用 Duration 对象进行日期时间数学运算,并传递给 plusminus。因此,您可能不需要将分钟数作为整数。但您可以询问持续时间的总分钟数。

long minutes = duration.toMinutes();

10

看到这个code run live at IdeOne.com

提示:在一段时间内使用时钟时间格式是自找麻烦。模棱两可导致混乱和错误。我建议对持续时间使用标准 ISO 8601 格式,因为它们的设计目的是明确、易于阅读和易于解析。

【讨论】:

    【解决方案2】:

    在 Java 8 中,您可以使用 DateTimeFormatter.ofLocalizedTime 来获取特定于语言环境的日期时间格式化程序。然后你可以用它来parse the string into a LocalTimeextract 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();
    }
    

    例子:

    System.out.println(getMinute("10.47", new Locale("fi")));   // 647
    System.out.println(getMinute("11:23", Locale.ROOT));        // 683
    

    如果您不关心时间分隔符,我们可以改用固定模式。

    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();
    }
    

    […] 表示可选,因此它将匹配HH:mmHH.mmHHmmHH:.mm

    【讨论】:

    • 如果语言环境是美国会有 DateTimeParseException,因为 timeString 是 'HH:mm" 格式而不是 'HH:mm aa'
    • @Lega 这意味着HH:mm 不是美国的预期语言环境格式。请参阅更新以获取替代方案。
    • return time.getMinute(); 将只返回 LocalTime 的分钟部分,这应该是 return time.getHour() * 60 + time.getMinute(); 从午夜返回分钟
    【解决方案3】:

    注意很优雅,但它会做的工作

    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);
    

    【讨论】:

      【解决方案4】:

      首先将时间解析为LocalTime 实例,然后使用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();
      

      结果超过 645

      【讨论】:

      • 如果语言环境是美国,这里也会出现 DateTimeParseException,因为输入是 'HH:mm" 格式而不是 'HH:mm aa'
      【解决方案5】:

      您可以使用getLocalizedDateTimePattern 方法获取用于初始化DateTimeFormatter 的模式,以使用给定的语言环境解析时间。第一个null 是您不需要的日期。

      String timePattern = DateTimeFormatterBuilder.getLocalizedDateTimePattern(
                  null, FormatStyle.SHORT, IsoChronology.INSTANCE, locale);
      

      然后你用它来创建一个格式化程序(注意你必须再次指定语言环境):

      DateTimeFormatter dtf = DateTimeFormatter.ofPattern(timePattern, locale);
      

      如果您希望 "HHcmm" 代替 SHORT 的时间格式而不是 locale,其中 'c' 是一个非数字字符,它是该 locale 的时间分隔符,那么:

      1. 从文本中提取数字

        String[] duration = durationString.split("\\D");
        int minutes = parseInt(duration[0])*60 + parseInt(duration[1]);
        
      2. 使用时间分隔符创建DateTimeFormatter

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern(
                String.format("HH%smm", timeSeparator), locale);
        LocalTime time = LocalTime.parse(text, dtf);
        int minutes = time.toSecondOfDay() / 60;
        

        如果你必须这样做

        int minutes = ChronoUnit.MINUTES.between(LocalTime.MIN, time);
        

      【讨论】:

      • 如果语言环境是美国,这里也会出现 DateTimeParseException,因为输入是 'HH:mm" 格式而不是 'HH:mm aa'
      猜你喜欢
      • 2020-10-27
      • 1970-01-01
      • 2017-01-04
      • 1970-01-01
      • 1970-01-01
      • 2016-01-11
      • 1970-01-01
      • 2016-01-14
      • 2015-11-09
      相关资源
      最近更新 更多