首先,您的示例字符串并不一致:8:30 pm
缺少填充为零。我会认为这是一个错字,应该是08:30 pm
。
不良串格式
顺便提一句,这些输入字符串格式是不期望的。 - 更好的方法是使用标准ISO 8601格式。 - 带AM/PM的12小时闹钟很麻烦。标准格式使用24小时制,时间为0-23小时。
- 间隔的标准符号是由斜杠分隔的一对日期时间字符串:2008-01-01T13:00/2008-01-01T13:56
。
您的输入字符串有另一个严重问题:没有指示offset-from-UTC或时区。如果没有抵消或时区,我们必须回到假设通用24小时的日子。这忽略了夏令时(DST)等异常情况,可能导致23或25小时长的天。
如果您知道传入字符串的时区,请将其作为第二个参数传递以获得正确的结果。
java.time
这个问题很老了。从那以后,Java用现代java.time类取代了麻烦的旧日期时间类(Date
,Calendar
等)。我们在下面的示例代码中使用java.time。
例类
这里是因为你的问题给出处理这些字符串一个完整的类。 A Duration
被生产。
package javatimestuff;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Locale;
/**
*
* @author Basil Bourque
*/
public class DurationProcessor {
static final int SHORT = 30;
static final int LONG = 41;
static final DateTimeFormatter FORMATTER_LOCALDATETIME = DateTimeFormatter.ofPattern ("uuuu-MM-dd hh:mm a");
static final DateTimeFormatter FORMATTER_LOCALTIME = DateTimeFormatter.ofPattern ("hh:mm a");
static public Duration process (String input) {
return DurationProcessor.process (input , ZoneOffset.UTC);
}
static public Duration process (String input , ZoneId zoneId) {
Duration d = Duration.ZERO; // Or maybe null. To be generated by the bottom of this code.
if (null == input) {
// …
System.out.println ("ERROR - Passed null argument.");
return d;
}
if (input.length() == 0) {
// …
System.out.println ("ERROR - Passed empty string as argument.");
return d;
}
String inputModified = input.toUpperCase (Locale.ENGLISH); // Change `am` `pm` to `AM` `PM` for parsing.
String[] parts = inputModified.split (" - ");
String inputStart = parts[ 0 ]; // A date-time sting.
String inputStop = parts[ 1 ]; // Either a date-time string or a time-only string (assume the same date).
ZonedDateTime start = null; // To be generated in this block of code.
try {
LocalDateTime ldt = LocalDateTime.parse (inputStart , DurationProcessor.FORMATTER_LOCALDATETIME);
start = ldt.atZone (zoneId);
} catch (DateTimeParseException e) {
// …
System.out.println ("ERROR - The start failed to parse. inputStart: " + inputStart);
return d;
}
ZonedDateTime stop = null; // To be generated in this block of code.
switch (input.length()) {
case DurationProcessor.SHORT: // Example: "2008-01-01 01:00 pm - 01:56 pm"
try {
LocalTime stopTime = LocalTime.parse (inputStop , DurationProcessor.FORMATTER_LOCALTIME);
stop = ZonedDateTime.of (start.toLocalDate() , stopTime , zoneId);
} catch (DateTimeParseException e) {
// …
System.out.println ("ERROR - The stop time failed to parse.");
return d;
}
break;
case DurationProcessor.LONG: // "2008-01-01 8:30 pm - 2008-01-02 09:30 am"
try {
LocalDateTime ldt = LocalDateTime.parse (inputStop , DurationProcessor.FORMATTER_LOCALDATETIME);
stop = ldt.atZone (zoneId);
} catch (DateTimeParseException e) {
// …
System.out.println ("ERROR - The stop date-time failed to parse.");
return d;
}
break;
default:
// …
System.out.println ("ERROR - Input string is of unexpected length: " + input.length());
break;
}
d = Duration.between (start , stop);
return d;
}
public static void main (String[] args) {
// Run with out time zone (assumes UTC).
Duration dShort = DurationProcessor.process ("2008-01-01 01:00 pm - 01:56 pm");
System.out.println ("dShort: " + dShort);
Duration dLong = DurationProcessor.process ("2008-01-01 08:30 pm - 2008-01-02 09:30 am");
System.out.println ("dLong: " + dLong);
// Run with specified time zone.
ZoneId z = ZoneId.of ("America/Montreal");
Duration dShortZoned = DurationProcessor.process ("2008-01-01 01:00 pm - 01:56 pm" , z);
System.out.println ("dShortZoned: " + dShortZoned);
Duration dLongZoned = DurationProcessor.process ("2008-01-01 08:30 pm - 2008-01-02 09:30 am" , z);
System.out.println ("dLongZoned: " + dLongZoned);
}
}
请注意类中的main
方法,例如用法。
首先是一对没有指定时区的呼叫。所以UTC和24小时的天数将被使用。
Duration dShort = DurationProcessor.process ("2008-01-01 01:00 pm - 01:56 pm");
System.out.println ("dShort: " + dShort);
Duration dLong = DurationProcessor.process ("2008-01-01 08:30 pm - 2008-01-02 09:30 am");
System.out.println ("dLong: " + dLong);
另一对调用我们指定的目标时区。
ZoneId z = ZoneId.of ("America/Montreal");
Duration dShortZoned = DurationProcessor.process ("2008-01-01 01:00 pm - 01:56 pm" , z);
System.out.println ("dShortZoned: " + dShortZoned);
Duration dLongZoned = DurationProcessor.process ("2008-01-01 08:30 pm - 2008-01-02 09:30 am" , z);
System.out.println ("dLongZoned: " + dLongZoned);
直播代码
见live code in IdeOne.com该类运行。
dShort:PT56M
dLong:PT13H
dShortZoned:PT56M
dLongZoned:PT13H
由于此页面上的其他地方所指出的,使用时间的输出格式日期风格如00:56
含糊不清,应该避免。 Duration
类改为使用标准ISO 8601 format for durations。上面,我们看到了56分钟和13分钟的结果。
关于java.time
的java.time框架是建立在Java 8和更高版本。这些类取代了日期时间类legacy,如java.util.Date
,Calendar
,& SimpleDateFormat
。
Joda-Time项目现在位于maintenance mode,建议迁移到java.time类。请参阅Oracle Tutorial。并搜索堆栈溢出了很多例子和解释。规格是JSR 310。
从何处获取java.time类?
的ThreeTen-Extra项目与其他类扩展java.time。这个项目是未来可能增加java.time的一个试验场。您可以在这里找到一些有用的类,如Interval
,YearWeek
,YearQuarter
和more。
输入不一致。大多数时间值的填充为零,但“8:30 pm”省略了这个值。 – 2017-01-28 23:58:25