【问题标题】:Convert hours, mins, secs String to hours将小时、分钟、秒字符串转换为小时
【发布时间】:2017-06-05 20:15:47
【问题描述】:

我想将以下格式的时间转换为小时。

我的时间格式输入可以是任何类似的东西

1 hour 30 mins 20 secs 
2 hrs 10 mins 
45 mins 

而我的输出将是:

1.505
2.167
0.75

现在是营业时间。

目前我通过解析输入字符串1 hour 30 mins 20 secs 来手动执行此操作,查找单词hour/hours/hrs/hr 是否存在,然后取前面的数字——分钟和秒相同。我使用公式手动将分钟和秒转换为小时。

有没有我可以在 Java 中使用的内置规定?

【问题讨论】:

  • 有一个用于自然语言处理的第三方库 JNLP,但那将是矫枉过正。
  • 你查过Joda-time吗?它具有包含这种可能性的句点解析功能。
  • 使用小数来表示以小时为单位的时间跨度是不明智的。我建议您查看持续时间的ISO 8601 标准格式,并查看java.time 类Durationjava.time.Duration.parse( "PT1H30M20S" )

标签: java time periodformatter


【解决方案1】:

另一种方法是将其解析为a Duration,但您需要先稍微更改格式。比如:

String adjusted = input.replaceAll("\\s+(hour|hr)[s]\\s+", "H");
//Do the same for minutes and seconds
//So adjusted looks like 1H30M20S
Duration d = Duration.parse("PT" + adjusted);

double result = d.toMillis() / 3_600_000d;

【讨论】:

  • 您不是说(hour|hr) 而不是[hour|hr] 吗?带有[] 的正则表达式与整个字符串“小时”或“小时”不匹配
  • 是的,当您在没有编译器的移动设备上编写代码时就会发生这种情况!
【解决方案2】:

通常我不会推荐 Joda-Time(因为它正在被新的 Java API 取代),但它是我所知道的唯一一个具有良好的句点格式化程序/解析器的 API。

您可以使用PeriodFormatterBuilder 类并使用appendSuffix 方法为每个字段定义单复数的后缀:

import org.joda.time.Period;
import org.joda.time.format.PeriodFormatter;
import org.joda.time.format.PeriodFormatterBuilder;

// method to parse the period
public void getPeriod(String input) {
    PeriodFormatter formatter = new PeriodFormatterBuilder()
            // hours (singular and plural suffixes)
            .appendHours().appendSuffix("hour", "hours")
            // minutes
            .appendMinutes().appendSuffix("min", "mins")
            // seconds
            .appendSeconds().appendSuffix("sec", "secs")
            // create formatter
            .toFormatter();

    // remove spaces and change "hr" to "hour"
    Period p = formatter.parsePeriod(input.replaceAll(" ", "").replaceAll("hr", "hour")); 

    double hours = p.getHours();
    hours += p.getMinutes() / 60d;
    hours += p.getSeconds() / 3600d;
    System.out.println(hours);
}

// tests
getPeriod("1 hour 30 mins 20 secs");
getPeriod("2 hrs 10 mins");
getPeriod("45 mins");

输出:

1.5055555555555555
2.1666666666666665
0.75


创建PeriodFormatter 的另一种方法是将appendSuffix 与正则表达式一起使用。当您有许多不同的后缀选项时(例如小时字段的hourhr),它很有用:

PeriodFormatter formatter = new PeriodFormatterBuilder()
    // hours (all possible suffixes for singular and plural)
    .appendHours()
    .appendSuffix(
        // regular expressions for singular and plural
        new String[] { "^1$", ".*", "^1$", ".*" },
        // possible suffixes for singular and plural
        new String[] { " hour", " hours", " hr", " hrs" })
    // optional space (if there are more fields)
    .appendSeparatorIfFieldsBefore(" ")
    // minutes
    .appendMinutes().appendSuffix(" min", " mins")
    // optional space (if there are more fields)
    .appendSeparatorIfFieldsBefore(" ")
    // seconds
    .appendSeconds().appendSuffix(" sec", " secs")
    // create formatter
    .toFormatter();

请注意,我还添加了appendSeparatorIfFieldsBefore(" ") 以表明它在下一个字段之前有一个空格。

这个版本的好处是你不需要对输入进行预处理:

// no need to call replaceAll (take input just as it is)
Period p = formatter.parsePeriod(input);

输出同上。


Java 8 日期时间 API

@assylian's answer 中所述,您可以使用java.time.Duration 类:

public void getDuration(String input) {
    // replace hour/min/secs strings for H, M and S
    String adjusted = input.replaceAll("\\s*(hour|hr)s?\\s*", "H");
    adjusted = adjusted.replaceAll("\\s*mins?\\s*", "M");
    adjusted = adjusted.replaceAll("\\s*secs?\\s*", "S");
    Duration d = Duration.parse("PT" + adjusted);

    double hours = d.toMillis() / 3600000d;
    System.out.println(hours);
}

//tests
getDuration("1 hour 30 mins 20 secs");
getDuration("2 hrs 10 mins");
getDuration("45 mins");

输出是一样的。

PS:如果你的 Java 版本是 ThreeTen Backport。类名和方法都是一样的,唯一不同的是包名:org.threeten.bp而不是java.time

【讨论】:

    【解决方案3】:

    目前我正在这样做:

    private double convertToHours(String inputTime) {
        inputTime = " 1 hour 30 mins 20 secs";
        double hours = 0;
        List<String> timeList = Arrays.asList(inputTime.split(" "));
        ListIterator<String> iterator = timeList.listIterator();
        String time = null;
        String previous = null;
        while (iterator.hasNext()) {
            int prevIndex = iterator.previousIndex();
            time = (String) iterator.next();
    
            if (!time.isEmpty() && time != null) {
    
                if (time.contains("hours") || time.contains("hrs") || time.contains("hr") || time.contains("hour")) {
                    // time = time.substring(0, time.indexOf('h'));
                        previous = timeList.get(prevIndex);
    
                    hours = hours + Double.parseDouble(previous.trim());
                }
    
                if (time.contains("mins") || time.contains("min") || time.contains("mns")) {
                    //time = time.substring(0, time.indexOf('m'));
                    previous = timeList.get(prevIndex);
                    hours = hours + Double.parseDouble(previous) / 60;
                }
    
                if (time.contains("secs") || time.contains("sec") || time.contains("scs")) {
                    //time = time.substring(0, time.indexOf('s'));
                    previous = timeList.get(prevIndex);
                    hours = hours + Double.parseDouble(previous) / 3600;
                }
            }
        }
        return hours;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-29
      • 1970-01-01
      • 2015-05-18
      • 2020-01-28
      • 2012-06-15
      • 2015-06-02
      • 2011-09-01
      相关资源
      最近更新 更多