我使用以下代码计算两个日期之间的秒数差异:
long secondsBetween = (Seconds.secondsBetween(new LocalDate("1901-01-01"), new LocalDate()).getSeconds());
但是我得到以下例外:
08-08 18:21:27.345: E/AndroidRuntime(6972): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.testbdr/com.testbdr.MainActivity}: java.lang.ArithmeticException: Value cannot fit in an int: 3584908800
08-08 18:21:27.345: E/AndroidRuntime(6972): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2189)
08-08 18:21:27.345: E/AndroidRuntime(6972): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2216)
08-08 18:21:27.345: E/AndroidRuntime(6972): at android.app.ActivityThread.access$600(ActivityThread.java:149)
08-08 18:21:27.345: E/AndroidRuntime(6972): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1305)
08-08 18:21:27.345: E/AndroidRuntime(6972): at android.os.Handler.dispatchMessage(Handler.java:99)
08-08 18:21:27.345: E/AndroidRuntime(6972): at android.os.Looper.loop(Looper.java:153)
08-08 18:21:27.345: E/AndroidRuntime(6972): at android.app.ActivityThread.main(ActivityThread.java:5000)
08-08 18:21:27.345: E/AndroidRuntime(6972): at java.lang.reflect.Method.invokeNative(Native Method)
08-08 18:21:27.345: E/AndroidRuntime(6972): at java.lang.reflect.Method.invoke(Method.java:511)
08-08 18:21:27.345: E/AndroidRuntime(6972): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:821)
08-08 18:21:27.345: E/AndroidRuntime(6972): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:584)
08-08 18:21:27.345: E/AndroidRuntime(6972): at dalvik.system.NativeStart.main(Native Method)
08-08 18:21:27.345: E/AndroidRuntime(6972): Caused by: java.lang.ArithmeticException: Value cannot fit in an int: 3584908800
08-08 18:21:27.345: E/AndroidRuntime(6972): at org.joda.time.field.FieldUtils.safeToInt(FieldUtils.java:206)
08-08 18:21:27.345: E/AndroidRuntime(6972): at org.joda.time.field.BaseDurationField.getDifference(BaseDurationField.java:141)
08-08 18:21:27.345: E/AndroidRuntime(6972): at org.joda.time.chrono.BaseChronology.get(BaseChronology.java:260)
08-08 18:21:27.345: E/AndroidRuntime(6972): at org.joda.time.base.BaseSingleFieldPeriod.between(BaseSingleFieldPeriod.java:105)
08-08 18:21:27.345: E/AndroidRuntime(6972): at org.joda.time.Seconds.secondsBetween(Seconds.java:124)
08-08 18:21:27.345: E/AndroidRuntime(6972): at com.testbdr.MainActivity.onCreate(MainActivity.java:27)
08-08 18:21:27.345: E/AndroidRuntime(6972): at android.app.Activity.performCreate(Activity.java:5020)
08-08 18:21:27.345: E/AndroidRuntime(6972): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
08-08 18:21:27.345: E/AndroidRuntime(6972): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2153)
08-08 18:21:27.345: E/AndroidRuntime(6972): ... 11 more
答案 0 :(得分:6)
int
正如其他答案正确陈述的那样,问题是你和Joda-Time正在使用int
来处理秒数。一个32位的int只能容纳大约68年的秒数。
如果您坚持使用秒来跟踪几个世纪的时间,则必须使用64位long
而不是32位int
。
顺便说一下,在Unix中使用32位int跟踪时间的秒数表示现实世界的问题知道Year 2038 problem。
正如其他人所说,使用秒来追踪如此长的时间跨度是不寻常的。如果可能的话,您可能想重新考虑这个前提。
另一种选择:ISO 8601标准提供Durations格式PnYnMnDTnHnMnS
格式的年数,月数,天数等。 Joda-Time知道如何解析和生成这样的字符串(Period和Duration类)。虽然Joda-Time只能处理int
数字几秒钟,但是当它以ISO 8601格式呈现为字符串时,它可以处理更多的秒数,如下面的代码示例(PT3584908800S
)。
Joda-Time使用毫秒内部跟踪来自epoch的计数。 Joda-Time提供了以long
值的形式访问这些毫秒的方法。
我通常建议您在几毫秒内完成日期工作。但在你的情况下,它是有道理的,根据需要转换为秒。
要计算毫秒数,我们需要使用DateTime而不是LocalDate。
养成调用方法withTimeAtStartOfDay
以获得当天第一时刻的习惯。此时间通常为00:00:00
,但并非总是因为夏令时或其他异常。
即使LocalDate
,时区也至关重要。日期(和一天的第一时刻)由时区决定。巴黎的新日早些时候比蒙特利尔更新。
如果省略时区,将使用JVM的当前默认时区。通常更好地明确并指定所需的时区。我怀疑你的目的,使用UTC有意义。
Joda-Time提供Duration类来表示解开时间轴(宇宙历史)的时间跨度。
使用Joda-Time 2.4的示例代码。
DateTime history = new DateTime( "1901-01-01", DateTimeZone.UTC ).withTimeAtStartOfDay(); // Technically, the call to withTimeAtStartOfDay is not necessary here as Joda-Time defaults to that for parsing a date-only string. But the call is a good habit and makes clear out intention.
DateTime today = new DateTime( DateTimeZone.UTC ).withTimeAtStartOfDay();
Duration duration = new Duration( history, today );
long millis = duration.getMillis(); // Use a long, not an int.
long seconds = ( millis / 1000L ); // Use a long, not an int. Maybe use BigDecimal or BigInteger if you want rounding.
转储到控制台。
System.out.println( "history: " + history );
System.out.println( "today: " + today );
System.out.println( "duration: " + duration );
System.out.println( "millis: " + millis );
System.out.println( "seconds: " + seconds );
跑步时。
history: 1901-01-01T00:00:00.000Z
today: 2014-08-08T00:00:00.000Z
duration: PT3584908800S
millis: 3584908800000
seconds: 3584908800
当走向另一个方向时,要么:
long
秒数传递给静态方法Duration.standardSeconds
。答案 1 :(得分:4)
JodaTime找到了差异,即3584908800秒。但是,它无法将相同的转换为int,因为int不能保存那么大的值。
你真的有一个旧日期(1-1-1901)的实际用例吗?
尝试使用不同的日期重新运行相同的日期,这会产生较小的差异。猜猜我们无法使用Seconds.secondsBetween()
方法实现这一目标。
注意:Java / Unix的日期系统使用1-1-1970作为起点。
答案 2 :(得分:3)
getSeconds is defined as returning an int:
public int getSeconds()
所以,即使你将结果存储在一个长期,它也只能返回一个数量< MAXINT或大约64年。简而言之,如果您确实需要计算世纪大小的时间段内的秒数,则此方法不适合您。
如您的示例测量两个日期之间的距离(以秒为单位),为什么不使用Hours.getHours()并将结果乘以3600?结果应该非常接近您想要的(除了我认为的闰秒),并为您提供足够大的可用范围以满足您的需求。
答案 3 :(得分:-2)
使用Seconds类
DateTime now = DateTime.now();
DateTime dateTime = now.plusMinutes(10);
Seconds seconds = Seconds.secondsBetween(now, dateTime);
System.out.println(seconds.getSeconds());
编辑:
Int类型的范围从-2,147,483,648到2,147,483,647。你的价值会给你类似的东西 3565987200。所以这种方法对你不起作用
解决方法:
Date d1 = ...;
Date d2 = ...;
long seconds = (d2.getTime()-d1.getTime())/1000;
答案 4 :(得分:-2)
查看http://joda-time.sourceforge.net/apidocs/org/joda/time/Seconds.html#secondsBetween(org.joda.time.ReadableInstant,org.joda.time.ReadableInstant)
long secondsBetween =(Seconds.secondsBetween(new LocalDate(“1901-01-01”),new LocalDate())。getSeconds());
我认为LocalDate())。getSeconds()是错误的,因为你想获得两个ReadableInstant之间的秒数。尝试Seconds.secondsBetween与2 LocalDates
请看这里:http://www.leveluplunch.com/java/examples/number-of-seconds-between-two-dates/
// start day is 1 day in the past
DateTime startDate = new DateTime().minusDays(1);
DateTime endDate = new DateTime();
Seconds seconds = Seconds.secondsBetween(startDate, endDate);
int secondsInDay = seconds.getSeconds();