[英]Java Time calculation
所以我的方法接收24小时格式的时间(“HH:MM:SS”)并返回一个字符串差异时间。 如果是当地时间下午2:00我应该能够“16:30:00”(下午4:30)发送它并输出“2小时30分钟”。 但代码有一些问题,我只是一个初学者,我需要帮助来解决它。
问题是如果时间是下午4:40,我发送它“17:00:00”(下午5:00)它返回消息:12小时20分钟而不是0小时20分钟。 另一个问题是,如果我发送当前时间,它将返回“12小时”,而不是像它应该的那样24。
请记住,我只是java的初学者,数学真的不是我的事,所以任何帮助都非常感谢。 谢谢。
private static String timeUntil(String distanceTime) {
String returnMsg = null;
try {
SimpleDateFormat sdfDate = new SimpleDateFormat("hh:mm:ss");
Date now = new Date();
java.text.DateFormat df = new java.text.SimpleDateFormat("hh:mm:ss");
Date date1 = df.parse(sdfDate.format(now));
Date date2 = df.parse(distanceTime);
long diff = date2.getTime() - date1.getTime();
int timeInSeconds = (int) (diff / 1000);
int hours, minutes;
hours = timeInSeconds / 3600;
timeInSeconds = timeInSeconds - (hours * 3600);
minutes = timeInSeconds / 60;
if (hours >= 0) {
returnMsg = hours + " hours" +
"\n" + minutes + " mins";
} else {
returnMsg = minutes + " mins";
}
} catch (Exception e) {
e.printStackTrace();
}
return returnMsg;
}
在您的日期格式中, hh
用于12小时。 使用HH
24小时:
new SimpleDateFormat("HH:mm:ss");
代码审查评论......
大多数Date类的方法都已弃用。 您应该考虑使用Calendar(GregorianCalendar)而不是Date。
您的变量名称通常缺乏意义 - 您必须知道变量的目的才能知道其含义。 如果使用更好的变量名,您的代码将更易于维护。 df可以重命名为“format”或“dateFormat”。
您现在创建一个Date对象,然后通过您的df DateFormat实例传递它,通过您的sdfDate实例,将其转换回Date。 这是不必要的。 将其替换为Date date1 = new Date();
并立即删除Date now = new Date();
。 同时,我看到在单位之间进行转换时很难诊断出错误,所以你应该改变diff
以表明它是毫秒,就像diff_ms
一样。 你应该保持名称一致 - 你从“不同”( diff
)变为“timeInSeconds”。 它们都应该是“timeInXxx”或“diff_xx”。 distanceTime
参数应该重命名为futureTime
你做了一堆数学来确定两次之间的差异,但有些库会为你做这件事。 谷歌为“两个日期之间的java差异”找到了很多答案。
您的代码始终假定第二次出现在“now”之后。 这应该包含在方法顶部的注释中。
当您实例化date1和date2时,它们可能都在同一天。 尝试调试或至少在创建对象后立即将对象打印到stdout以查看是否是这种情况。 这是你真正想要的吗?
您的代码不处理闰年。
而不是自己处理所有的时间转换,为什么不寻找适合您的库?
这是你的固定代码。 我已将日期格式更改为HH:mm:ss以及您的计算逻辑。 试一试,告诉我们
private static String timeUntil(String distanceTime) {
String returnMsg = null;
try {
SimpleDateFormat sdfDate = new SimpleDateFormat("HH:mm:ss");
Date now = new Date();
java.text.DateFormat df = new java.text.SimpleDateFormat("HH:mm:ss");
Date date1 = df.parse(sdfDate.format(now));
Date date2 = df.parse(distanceTime);
long diff = date2.getTime() - date1.getTime();
int timeInSeconds = (int) (diff / 1000);
int hours, minutes;
hours = timeInSeconds / 3600;
timeInSeconds = timeInSeconds - (hours * 3600);
minutes = timeInSeconds / 60;
if (hours != 0) {
returnMsg = hours + " hours" +
"\n" + minutes + " mins";
} else {
returnMsg = minutes + " mins";
}
} catch (Exception e) {
e.printStackTrace();
}
return returnMsg;
}
这是一个更健壮的例子,并使用Java更现代的日期函数。 我可以一点一点地指出你可以在你的例子中做得更好的事情,但有时它更容易给你一个很好的例子,让你从其他人的代码中收集你所能做的好的风格。
import java.util.Calendar;
public class testSpace {
public static void main (String ... args){
System.out.println(timeUntil("00:12:12"));
}
private static String timeUntil(String distanceTime){
String[] times = distanceTime.split(":");
Calendar now = Calendar.getInstance();
Calendar then = Calendar.getInstance();
then.set(Calendar.SECOND, Integer.parseInt(times[2]));
then.set(Calendar.MINUTE, Integer.parseInt(times[1]));
then.set(Calendar.HOUR, Integer.parseInt(times[0]) % 12);
then.set(Calendar.AM_PM, (Integer.parseInt(times[0]) >= 12 ) ? Calendar.PM : Calendar.AM);
boolean isFuture = (then.getTimeInMillis() > now.getTimeInMillis());
long interval = (isFuture)
? then.getTimeInMillis() - now.getTimeInMillis()
: now.getTimeInMillis() - then.getTimeInMillis();
return ((isFuture) ? "" : "-") + millToTime(interval);
}
public static long MILLISECOND_PER_HOUR = 1000*60*60;
public static long MILLISECOND_PER_MIN = 1000*60;
public static long MILLISECOND_PER_SECOND = 1000;
public static String millToTime(long mill){
long hours = mill / MILLISECOND_PER_HOUR;
long mins = (mill % MILLISECOND_PER_HOUR) / MILLISECOND_PER_MIN;
long sec = ((mill % MILLISECOND_PER_HOUR) % MILLISECOND_PER_MIN) / MILLISECOND_PER_SECOND;
return String.format("%d:%d:%d", hours, mins, sec);
}
}
仅适用于时间,没有日期或时区。
LocalTime start = LocalTime.of( "16:40" ) ;
LocalTime stop = LocalTime.of( "17:00" ) ;
Duration d = Duration.between( start , stop ) ;
PT20M
或者,对于区域中的日期时间。
ZoneId z = ZoneId.of( "America/Montreal" )
ZonedDateTime zdtNow = ZonedDateTime.now( z );
ZonedDateTime zdtThen =
ZonedDateTime.of( // Pass a LocalDate, LocalTime, ZoneId.
zdtNow.toLocalDate() , // Same date…
LocalTime.parse( "16:30:00" ) , // … but different time-of-day.
z
)
Duration d = Duration.between( zdtNow , zdtThen ) ;
PT2H30M
您正在使用旧的日期时间类,现在是旧的,由java.time类取代。
LocalTime
您错误地将日期时间类用于仅限时间的值。 而是使用LocalTime
类。 并在计算经过时间时使用时间跨度类。
String input = "16:30:00" ;
LocalTime lt = LocalTime.parse( input );
Instant
Instant
类表示UTC时间轴上的一个时刻,分辨率为纳秒 (最多九(9)位小数)。
Instant instant = Instant.now();
ZonedDateTime
确定挂钟时间需要一个时区。 以continent/region
的格式指定适当的时区名称 ,例如America/Montreal
, Africa/Casablanca
或Pacific/Auckland
。 切勿使用3-4字母缩写,例如EST
或IST
因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdtNow = instant.atZone( z ); // Adjusted into your time zone.
现在为您指定的输入时间构建ZonedDateTime
。
ZonedDateTime zdtTarget = ZonedDateTime.of( zdtNow.toLocalDate() , lt , z );
Duration
使用Duration
表示未附加到时间线的已用时间。
Duration d = Duration.between( zdtNow , zdtTarget );
请注意,如果指定的时间早于当前时间,则持续时间将为负数。
要获取描述该时间跨度的小时,分钟等的字符串,只需调用toString
以标准ISO 8601格式生成PnYnMnDTnHnMnS
的字符串,其中P
标记开头, T
将年 - 月 - 日与小时 - 分钟分开-seconds。
如果同一区域的当前时间是14:00:00
,则输出为:
PT2H30M
奇怪的是,在Java 8中,这个类Duration
缺少任何部件的getter方法,例如2
小时和30
分钟。 使用 toHoursPart
和toMinutesPart
等方法在Java 9中进行了 toMinutesPart
。
java.time框架内置于Java 8及更高版本中。 这些类取代了麻烦的旧遗留日期时间类,如java.util.Date
, Calendar
和SimpleDateFormat
。
现在处于维护模式的Joda-Time项目建议迁移到java.time。
要了解更多信息,请参阅Oracle教程 。 并搜索Stack Overflow以获取许多示例和解释。 规范是JSR 310 。
从哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展了java.time。 该项目是未来可能添加到java.time的试验场。 您可以在这里找到一些有用的类,比如Interval
, YearWeek
, YearQuarter
,和更多 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.