我尝试了以下代码。 当开始时间和结束时间之间存在小时/日期差时,java时间差输出负值和错误值
Date d3 = null;
Date d4 = null;
List<String> activeTimeList = new ArrayList();
int c = Integer.parseInt(cycle.get("Cycle No:").toString());
try {
for(int i = 0; i<c;i++) {
SimpleDateFormat format = new SimpleDateFormat("MM-dd-yyyy HH:mm", Locale.US); //("MM/dd/yyyy HH:mm:ss");
format.setTimeZone(TimeZone.getTimeZone("GMT"));
String cycleEndTm = cycle.get("End Time"+i+"").toString().trim();
String cycleStartTm = cycle.get("Start Time"+i+"").toString().trim();
d3 = format.parse(cycleEndTm);
d4 = format.parse(cycleStartTm);
long diff = d3.getTime() - d4.getTime();
long diffSeconds = diff / 1000 % 60;
long diffMinutes = diff / (60 * 1000) % 60;
long diffHours = diff / (60 * 60 * 1000) % 24;
long diffDays = diff / (24 * 60 * 60 * 1000);
String time1 = diffDays+"."+diffHours+"."+diffMinutes+"."+diffSeconds;
Log :
0.-10.-7.0
d4 = 02-11-2017 16:47
d3 = 02-11-2017 17:27差异= 0.-10.-7.0
无法获得正确的时差?我在这里想念的是什么?
注意**:cycleEndTm -cycleStarttime应该给出正结果。我正在从地图中读取cycleEndTime和开始时间。那就是要求。
答案 0 :(得分:2)
使用现代的 java.time 类,切勿Date
。将任何Date
转换为java.time.Instant
。
Duration // Represent a span-of-time as 24-hour days, hours, minutes, seconds, and nanoseconds.
.between( // Calculate elapsed time.
javaUtilDateStart.toInstant() , // Convert any `java.util.Date` to `java.time.Instant`. Never use `Date`; it is a terrible class, ditto for `Calendar`.
javaUtilDateStop.toInstant()
) // Returns a `Duration` object.
.toString() // Generate text in standard ISO 8601 format.
或调用to…Part
方法以提取天数,小时数等。
您使用的是可怕的旧日期时间类(Date
,Calendar
,SimpleDateFormat
),这些类早在几年前就被 java.time 类所取代。
Instant
很显然,您将获得一个java.util.Date
对象。如果可能,请重写该代码以使用其替换java.time.Instant
对象。两者都代表UTC的时刻,但是Instant
的分辨率更佳,为纳秒而不是毫秒。如果不可能,请立即将Date
转换为Instant
。调用添加到旧类中的新转换方法。
Instant instant = myJavaUtilDate.toInstant() ; // Convert from legacy class to modern class. Same moment in UTC, same point on the timeline.
以标准ISO 8601格式生成表示该时刻的文本。
使用UTC捕获当前时刻。
Instant now = Instant.now() ; // Capture the current moment in UTC.
Duration
将经过时间计算为Duration
对象。同样,这具有纳秒级的分辨率。
Duration d = Duration.between( instant , now ) ;
以标准ISO 8601格式生成表示经过时间的文本。
String output = d.toString() ;
或者创建您的字符串,将“天”定义为24小时制,而不考虑日历。
long days = d.toDaysPart() ;
int hours = d.toHoursPart() ;
int minutes = d.toMinutesPart() ;
int seconds = d.toSecondsPart() ;
String output = days + "." + hours + "." + minutes + "." + seconds ;
您的问题不清楚您的输入内容。如果以字符串开头,则进行解析。首先,如果可能,请更改这些字符串的源,以使用明智定义的ISO 8601标准格式。如果可能的话,请定义一个格式化模式以匹配输入。
String inputStart = "02-10-2018 10.30";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd-MM-uuuu HH.mm" );
将您的输入解析为LocalDateTime
,因为它没有任何时区或自UTC偏移的指示。
LocalDateTime ldtStart = LocalDateTime.parse( inputStart , f ) ;
LocalDateTime
不是不是时刻,不是表示时间轴上的一个点。此类表示大约26-27小时(全球时区范围)内的潜在时刻。
分配该字符串源所要使用的区域或偏移量,以提供确定力矩所需的上下文。
以continent/region
的格式指定proper time zone name,例如America/Montreal
,Africa/Casablanca
或Pacific/Auckland
。切勿使用2-4个字母的缩写,例如EST
或IST
,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。
// Transform the indefinite `LocalDateTime` to a definite moment by assigning the time zone intended by that input string.
ZoneId z = ZoneId.of( "Africa/Tunis" );
ZonedDateTime zdtStart = ldtStart.atZone( z );
计算您的时间跨度。
Duration d = Duration.between( zdtStart , zdtStop ) ;
java.time框架已内置在Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和SimpleDateFormat
。
目前位于Joda-Time的maintenance mode项目建议迁移到java.time类。
要了解更多信息,请参见Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310。
您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*
类。
在哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如Interval
,YearWeek
,YearQuarter
和more。
答案 1 :(得分:1)
此答案不能解决您提出的问题。无论如何,我建议使用现代Java日期和时间API java.time。这里的第一个版本至少需要 Java 9 。 Java 6、7和8会更进一步。
Map<String, Object> cycle = Map.of("Cycle No:", 1,
"Start Time0", "02-11-2017 16:47",
"End Time0", "02-11-2017 17:27");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd-yyyy HH:mm", Locale.US);
List<String> activeTimeList = new ArrayList<>();
int c = Integer.parseInt(cycle.get("Cycle No:").toString());
try {
for(int i = 0; i < c; i++) {
String cycleEndTm = cycle.get("End Time" + i).toString().trim();
String cycleStartTm = cycle.get("Start Time" + i).toString().trim();
LocalDateTime d4 = LocalDateTime.parse(cycleStartTm, formatter);
LocalDateTime d3 = LocalDateTime.parse(cycleEndTm, formatter);
Duration diff = Duration.between(d4, d3);
String time1 = String.format(Locale.US, "%d.%d.%d.%d",
diff.toDays(), diff.toHoursPart(),
diff.toMinutesPart(), diff.toSecondsPart());
activeTimeList.add(time1);
}
System.out.println(activeTimeList);
} catch (DateTimeParseException dtpe) {
System.err.println(dtpe);
}
此打印:
[0.0.40.0]
我用于格式化的toXxxPart
类的Duration
方法不在 Java 8 中。因此,如果您使用的是Java 8,则可以使用这种方式进行格式化:
long days = diff.toDays();
diff = diff.minusDays(days);
long hours = diff.toHours();
diff = diff.minusHours(hours);
long minutes = diff.toMinutes();
diff = diff.minusMinutes(minutes);
long seconds = diff.getSeconds();
String time1 = String.format(Locale.US, "%d.%d.%d.%d",
days, hours, minutes, seconds);
输出与以前相同。
如果一起阅读的任何人正在使用 Java 6或7 ,请获取the ThreeTen Backport library,并且Java 8代码也应该在那里使用。
您发布的代码中唯一的问题是您使用的是过时的,设计不佳的日期和时间类Date
,SimpleDateFormat
和TimeZone
。您的代码中没有任何内容可以解释您是如何得到错误的负值,因此我怀疑您没有在解析您认为自己在解析的字符串。
答案 2 :(得分:0)
您可以使用 java.time.Duration
,它以 ISO-8601 standards 为模型,并作为 JSR-310 implementation 的一部分与 Java-8 一起引入。 Java-9 引入了一些更方便的方法。
演示:
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String d4 = "02-11-2017 16:47";
String d3 = "02-11-2017 17:27";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd-MM-uuuu HH:mm", Locale.ENGLISH);
// The given date-times in UTC
OffsetDateTime odtD4 = LocalDateTime.parse(d4, dtf).atOffset(ZoneOffset.UTC);
OffsetDateTime odtD3 = LocalDateTime.parse(d3, dtf).atOffset(ZoneOffset.UTC);
// Duration between the date-times in UTC
Duration duration = Duration.between(odtD4, odtD3);
System.out.println(duration);
// Custom format
// ####################################Java-8####################################
String formattedDuration = String.format("%02d.%02d.%02d.%02d", duration.toDays(), duration.toHours() % 24,
duration.toMinutes() % 60, duration.toSeconds() % 60);
System.out.println(formattedDuration);
// ##############################################################################
// ####################################Java-9####################################
formattedDuration = String.format("%02d.%02d.%02d.%02d", duration.toDaysPart(), duration.toHoursPart(),
duration.toMinutesPart(), duration.toSecondsPart());
System.out.println(formattedDuration);
// ##############################################################################
}
}
输出:
PT40M
00.00.40.00
00.00.40.00
从 Trail: Date Time 了解现代日期时间 API。