将小时,分钟,秒转换为小时字符串

问题描述:

我想将以下格式的时间转换为小时。将小时,分钟,秒转换为小时字符串

我输入这是一个时间格式也能像

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中使用的内置规定吗?

+0

有一个thrird党库** ** JNLP自然语言处理,但是这将是矫枉过正。 –

+0

你检查了乔达时间吗?它具有包含这种可能性的周期分析功能。 – RealSkeptic

+1

使用小数来表示以小时为单位的时间跨度是不明智的。我建议你查看[ISO 8601](https://en.wikipedia.org/wiki/ISO_8601#Durations)标准格式的持续时间,并查看java.time类['Duration'](https:// docs.oracle.com/javase/8/docs/api/java/time/Duration.html)。 'java.time.Duration.parse(“PT1H30M20S”)' –

另一种方法是将其解析为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; 
+0

您是不是指'(小时|小时)'而不是'[小时|小时]'?使用'[]'的正则表达式不匹配整个字符串“hour”或“hr” – 2017-06-05 21:58:01

+1

确实,这就是当您在没有编译器的情况下在移动设备上编写代码时发生的情况! – assylias

通常我不会推荐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

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(" ")以表明它有下一个前场的空间:当你有很多的后缀不同的选项(如hourhr的时间字段)这是非常有用的。

关于这个版本的好处是,你不需要预先处理输入:

// 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版本是< = 7,您可以使用ThreeTen Backport。类名和方法是相同的,唯一的区别是包名称:org.threeten.bp而不是java.time

目前我在做这样的:

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