jodaorg / joda-time Goto Github PK
View Code? Open in Web Editor NEWJoda-Time is the widely used replacement for the Java date and time classes prior to Java SE 8.
Home Page: http://www.joda.org/joda-time/
License: Apache License 2.0
Joda-Time is the widely used replacement for the Java date and time classes prior to Java SE 8.
Home Page: http://www.joda.org/joda-time/
License: Apache License 2.0
Hi!
I am running into an issue that just started this month. Here is come sample code:
DateTime now = new DateTime();
now = now.minusMonths(11);
now = now.minusWeeks(3);
now = now.plusMonths(11);
System.out.println(Weeks.weeksBetween(now, new DateTime()).getWeeks());
weeksBetween will return 2 instead of 3. Anyone know why this is occurring? I am using 2.2 version of the API.
Thanks!
about the february month there is a strange behavior that you can see in the incorect results with jodatime, you can look down here :
DateTime date4 = new DateTime(2013, 5, 29, 0, 0, 0, 0);
DateTime date4PlusNineMonths = new DateTime(2014, 2, 28, 0, 0, 0, 0);
Period period4 = new Period(date4, date4PlusNineMonths);
//Incorrect result
System.out.print(date4.toString("dd/MM/YYYY")+".plusMonths(9) = "+ date4.plusMonths(9).toString("dd/MM/YYYY"));
System.out.print(period4.getYears() +"Years/"+ period4.getMonths() +"Months/"+ period4.getWeeks() +"Weeks/"+ period4.getDays() +"Days");
Output :
29/05/2013.plusMonths(9) = 28/02/2014 //incorrect result should be 01/03/2014
0Years/9Months/0Weeks/0Days
This is an incorrect calculation It should be 0Years/8Months/4Weeks/2Days Isn't it...?
If it is correct so why when I increase two days more (30 and 31) it always give me the same calculation (0Years/9Months/0Weeks/0Days) we all agree that days are really decreasing or am I dreaming...?
Now maybe I wrong in my use of the joda framework because in the app I develop I do a check everyday on a period to have the precise month separation between two date (toDay and the next date) and if I have 9months and 1day it's too late I need to have 9months and 0days as required in my app =/
If I wrong how can I achieve this please...?
The ReadableInstant
interface only provides comparison methods representing the mathematical relations <
, =
, and >
.
However, <=
and >=
are common as well, but they are not available as methods to compare instants with. This leads either to the creation of additional local utility methods (unfavorable), or to less readable, less expressive code like !entity.getCreatedAt().isAfter(today)
(where the negation, !
, is written far from the call to the method whose result value is to be negated, and thus too easily overlooked).
With the suggested methods, the above code be written more clearly as entity.getCreatedAt().isBeforeOrEqual(today)
.
Please consider adding those methods. Dealing with date/time is already hard enough ;)
The time zone is "America/Rio_Branco". I tried LocalDateTime 2:30am, 3:30am, 4:30am of June 24th, 2008, and all of them returned true, meaning the local time was set forward for 3 hours. But according to official record, there should be only 1-hour gap.
Currently only lines and source is included into debug info in maven-compile-plugin
Hi,
In order to save the current state in an android application, a java.util.Date object is created from a DateTime object using toDate(). However it seems that the resulting Date object is not properly serializable any more.
We use joda-time 2.2.
outState.putSerializable(ARG_SELECTED_DATE, selectedDate.toDate());
...
DateTime selectedDate = new DateTime(savedInstanceState.getSerializable(ARG_SELECTED_DATE));
java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = org.joda.time.DateTime)
at android.os.Parcel.writeSerializable(Parcel.java:1279)
at android.os.Parcel.writeValue(Parcel.java:1233)
at android.os.Parcel.writeMapInternal(Parcel.java:591)
at android.os.Bundle.writeToParcel(Bundle.java:1627)
at android.os.Parcel.writeBundle(Parcel.java:605)
at android.support.v4.app.FragmentState.writeToParcel(Fragment.java:132)
at android.os.Parcel.writeTypedArray(Parcel.java:1102)
at android.support.v4.app.FragmentManagerState.writeToParcel(FragmentManager.java:357)
at android.os.Parcel.writeParcelable(Parcel.java:1254)
at android.os.Parcel.writeValue(Parcel.java:1173)
at android.os.Parcel.writeMapInternal(Parcel.java:591)
at android.os.Bundle.writeToParcel(Bundle.java:1627)
at android.os.Parcel.writeBundle(Parcel.java:605)
at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:2252)
at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3052)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5041)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.io.NotSerializableException: org.joda.time.tz.CachedDateTimeZone$Info
at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1364)
at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1671)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1517)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1481)
at java.io.ObjectOutputStream.writeNewArray(ObjectOutputStream.java:1205)
at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1662)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1517)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1481)
at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:979)
at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:368)
at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1074)
at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1404)
at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1671)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1517)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1481)
at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:979)
at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:368)
at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1074)
at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1404)
at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1671)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1517)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1481)
at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:979)
at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:368)
at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1074)
at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1404)
at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1671)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1517)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1481)
at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:979)
at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:368)
at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1074)
at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1404)
at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1671)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1517)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1481)
at android.os.Parcel.writeSerializable(Parcel.java:1274)
... 23 more
Using a LenientChronology when parsing a time using 12-hour format yields a result in which the am/pm are flipped. On inspection, the issue is in LenientDateTimeField#set(long,int) where the delta between the current and desired value is being calculated. Because this particular field maps its zero value to 12, this ends up generating an incorrect delta, shifting results by 12 hours.
This can be reproduced with the following test:
public void lenientHourOfHalfDay() {
Chronology utc= ISOChronology.getInstanceUTC();
DateTimeFormatter format= DateTimeFormat.forPattern("h:mm a").withChronology(utc);
String text= "3:30 am";
DateTime result= format.parseDateTime(text);
DateTime lenientResult= format.withChronology(LenientChronology.getInstance(utc)).parseDateTime(text);
LocalTime expected= new LocalTime(3, 30);
// Works, as expected
Assert.assertEquals("Strict parse result wrong", expected, result.toLocalTime());
// Fails unexpectedly; value shifted by 12 hours
Assert.assertEquals("Lenient parse result wrong", expected, lenientResult.withChronology(utc).toLocalTime());
}
According to Wikipedia, 1900 shouldn't be a leap year.
http://en.wikipedia.org/wiki/List_of_leap_years
http://en.wikipedia.org/wiki/Leap_year
As such, century years must be divisible by 400 before they are classed as leap years.
Here's a unit test.
@Test
public void testExcelDateIn1900InMarch() {
int days = Days.daysBetween(new DateMidnight(1900, 1, 1),
new DateMidnight(1900, 3, 1)).getDays() + 1;
assertEquals(61, days);
}
Using joda-time 2.3 comparing two dates in different timezones is not working as expected. I would expect that if I send in two instances which when passed to the same timezone are on the same day the comparator will say they are on the same day. This is not the case, see small example below.
Even comparing the same instances in time, just in a different timezone (and even on the same day in their respective timezone) is failing.
The current behaviour is not documenting the problem of different timezones.
DateTimeZone HONG_KONG_TZ = DateTimeZone.forID("Asia/Hong_Kong");
DateTime date1 = new DateTime(2013, 10, 2, 11, 30, 53, 512, HONG_KONG_TZ)
DateTime date2 = date1.toDateTime(DateTimeZone.UTC)
DateTimeComparator.getDateOnlyInstance().compare(date1, date2)
The result is not 0 as you would expect, but -1. Calling the comparator with date2.toDateTime(HONG_KONG_TZ) correctly returns 0.
In an enterprise environment where there are many isolated applications that utilize joda-time, updating the version of joda-time in each application can be time-consuming and could be considered bad practice to change a deployed application. With the availability of the tzupdater utility [1] for Sun/Oracle JREs, updating the time zone recognized by the JRE has become a fairly trivial, one step process (per JRE). It would be beneficial to have an option for joda-time to use the time zone information provided by the JRE.
With the understanding that joda-time was written prior to the availability of the tzupdater and the fact that the tzupdater may be an enterprise-level solution, I would envision this enhancement as an optional feature that can be turned on (or off) as needed.
[1] - http://www.oracle.com/technetwork/java/javase/tzupdater-readme-136440.html
When a DateTimeZone is build with duplicate-named 'recurring saving time' in a first thread, all goes Ok: a warning message is generated and an identifier is automatically generated in PrecalculatedZone.create(). When a second thread does the same, an NPE is generated in ZoneInfoCompiler.verbose().
The cause is that the cVerbose ThreadLocal is incorrectly initialized in ZoneInfoCompiler:
static {
cVerbose.set(Boolean.FALSE);
}
...will initialize cVerbose only for the first thread and not for the subsequent ones. The NPE is caused by the autoboxing in:
public static boolean verbose() {
return cVerbose.get();
}
A better approach could be to remove the initialization and test for null:
public static boolean verbose(){
Boolean verbose = cVerbose.get();
return (verbose != null) ? verbose : false;
}
Here follows a test case:
@Test
public void testDateTimeZoneBuilder() throws Exception {
getTestDataTimeZoneBuilder().toDateTimeZone("TestDTZ1", true);
Thread t = new Thread(new Runnable() {
@Override
public void run() {
getTestDataTimeZoneBuilder().toDateTimeZone("TestDTZ2", true);
}
});
t.start();
t.join();
}
private DateTimeZoneBuilder getTestDataTimeZoneBuilder() {
return new DateTimeZoneBuilder()
.addCutover(1601, 'w', 1, 1, 1, false, 7200000)
.setStandardOffset(3600000)
.addRecurringSavings("", 3600000, 1601, Integer.MAX_VALUE, 'w', 3, -1, 1, false, 7200000)
.addRecurringSavings("", 0, 1601, Integer.MAX_VALUE, 'w', 10, -1, 1, false, 10800000);
}
Hello I've come across a number of problems related to the equals() methods (or lack thereof) in Chronology classes.
I was comparing 2 DateTime instances which have the same date, time and timezone but still DateTime.equals() returns false.
So I started to investigate...
DateTime.equals is in fact inherited from AbstractInstant. Looking at the docs and code of AbstractInstant.equals() I found out it checks both the milliseconds and the chronology. The millisecond comparison works fine (and returns true for my test data), however the comparison of chronologies does not work as it should.
Even though the Chronology objects of my DateTime objects were both "ISOChronology[Africa/Brazzaville]" (result of toString()) they were not considered equal.
So I dug deeper. In the code of AbstractInstant I saw that the Chronology comparison is performed using FieldUtils.equals(object, object), which in turns calls the object1.equals(object2) -- i.e. the method ISOChronology.equals() is called, which reads as follows:
public boolean equals(Object obj) {
return super.equals(obj);
}
Hence, when super.equals(obj) is called in ISOChronology none of the chronology fields are compared, and the result is solely based on object comparison. This is clearly a bug I would argue.
Note: You might wonder how I ever got to have 2 instances of ISOChronology for the same timezone. The reason is that I use an object database (DB4O) to store DateTime instances, and sometimes I need to handle finding duplicates cross multiple dumps of the database (containing largely the same data, but stored in different objects).
I have problem with DateTimeFormatterBuilder.
In Joda 2.1 this code is working without any problem:
DateTimeFormatterBuilder a = new DateTimeFormatterBuilder();
a.append(DateTimeFormat.forPattern("HH:mm"));
a.appendOptional(DateTimeFormat.forPattern(":ss").getParser());
a.appendOptional(DateTimeFormat.forPattern(".SSS").getParser());
a.append(DateTimeFormat.forPattern(":ss.SSS").getPrinter());
DateTimeFormatter f = a.toFormatter();
DateTime c = f.parseDateTime("05:04:59");
System.out.println(f.print(c));
But it does not work anymore in newer versions. I tried versions 2.2 and 2.3.
a.toFormatter() raises exception:
Both printing and parsing not supported
The problem occurs only when appendOptional method is used.
What was changed that it stopped working?
Thank you for your help.
I would like to know an appropriate way to create a DateTime from the (astronomical) Julian Day.
DateTimeUtils.fromJulianDay does not seem to work in its own.
Maybe this is my misunderstanding, but
new DateTime(DateTimeUtils.fromJulianDay(0)).getYear() // -4713
should give -4712 (that is 4713 BC) and not as currently -4713, is it not?
( from https://en.wikipedia.org/wiki/Julian_day#Calculation )
As in 310 project a common class that I always have to create in my projects is Month
http://threeten.github.io/threetenbp/apidocs/org/threeten/bp/Month.html
Could this be added in JodaTime?
In the DateTimeFormat
documentation, the symbol S
is described as a number
, and number's have the following description: "The minimum number of digits. Shorter numbers are zero-padded to this amount.".
However, S
doesn't adhere to this description, for example:
DateTimeFormatter format = DateTimeFormat.forPattern("S")
format.parseDateTime("1") # All is well
format.parseDateTime("12") # IllegalArgumentException: Invalid format
S
actually represents the exact number of digits, not the minimum.
I suggest adding a new presentation
to the documentation in DateTimeFormat
with a description that matches the behaviour of S
. I think this is the right behaviour for S
, and the documentation just needs updating but I thought I should double check before raising a pull request. If it's the expected behaviour I'll submit a PR with a change to the docs :)
currently the equals javadoc says
Returns:
true if the start and end millis are equal
this is not correct, it also compares the chronology. I know it mentions it just above, but I think the return comment should be updated as well.
Also, it would be nice if there was an isEqual method, similar to the one for AbstractInstant
Currently the only way I have found to do this check is something like
return interval1.getStart().isEqual(interval2.getStart()) && interval1.getEnd().isEqual(interval2.getEnd());
Hi,
I have seen a weird issue with DateTimeFormatter
lately, and after some googling without anything similar, I think it might be a bug in the parsing logic of joda-time
2.2
and 2.1
.
For example, the below code...
String text = "Tue Aug 11 21:41:19 2013";
DateTimeFormatter formatter = DateTimeFormat.forPattern("EEE MMM dd HH:mm:ss yyyy");
DateTime dateTime = formatter.parseDateTime(text);
assertThat(formatter.print(dateTime), is(text));
... fails with:
java.lang.AssertionError:
Expected: is "Tue Aug 11 21:41:19 2013"
but: was "Tue Aug 06 21:41:19 2013"
If you debug this, you will see that parseDateTime
somehow transforms 11th of August into the 6th of August.
Besides the same happens with the pattern: "EEE MMM dd HH:mm:ss ZZZ yyyy"
and strings like: "Tue Aug 11 21:41:19 Europe/London 2013"
.
Would you be able to:
I am happy to try to provide a patch if you point me to the right direction (where is what, etc.).
Cheers,
M.
According the JavaDocs numbers are parsed this way: "Number: The minimum number of digits. Shorter numbers are zero-padded to this amount."
Consider this code:
DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM");
DateTime dt = fmt.parseDateTime("2013-9");
It does not throw an expection, it silently ignores the fact that a padding zero is necessary. Java's SimpleDateFormat at least documents this inconsistency. Anyway, I would expect parsing to work the very same way as formatting a DateTime.
Hi, I have noticed that the hashcode for LocalDate is cached in:
/** The cached hash code. */
private transient volatile int iHash;
this code does not need to be volatile, volatile introduces uneeded overhead every time hascode is invoked.
if this field is not volatile the hashcode will be computed in the worst case scenario more than once, but I believe this is a more acceptable approach.
String hashcode caching is implemented whithoud a volatile field as well...
I wanted to browse the release notes for the latest releases, since I missed the last updates. I had a bad time finding the release notes in the first place, and then I found myself going through the commits of https://github.com/JodaOrg/joda-time/blob/master/RELEASE-NOTES.txt. I don't think this is intended.
Regards,
Benjamin
final LocalDate january12012 = new LocalDate(2012, 1,1);
final LocalDate february292012 = new LocalDate(2012, 2, 29);
// OK
assertEquals(59, Days.daysBetween(january12012, february292012).getDays());
final MonthDay january1 = new MonthDay(1,1);
final MonthDay february29 = new MonthDay(2, 29);
// FAIL
assertEquals(59, Days.daysBetween(january1, february29).getDays());
org.joda.time.IllegalFieldValueException: Value 29 for dayOfMonth must be in the range [1,28]
at org.joda.time.field.FieldUtils.verifyValueBounds(FieldUtils.java:217)
at org.joda.time.field.PreciseDurationDateTimeField.set(PreciseDurationDateTimeField.java:78)
at org.joda.time.chrono.BaseChronology.set(BaseChronology.java:240)
at org.joda.time.base.BaseSingleFieldPeriod.between(BaseSingleFieldPeriod.java:103)
at org.joda.time.Days.daysBetween(Days.java:141)
Is there a way to avoid this happening? I understand fiddling around with the leap year, you're bound to get issues.
Thanks!
I think that the possibility of obtaining, in an easy way, the Interval which results of adding a Duration to a given Interval, would enhance the features of Joda Time.
E.g. right now I have an Interval representing the time for a lecture in an administrative app for a university, so that the following lecture is exactly one week ahead. I would like to obtain the Interval for the following lecture just by writing
firstLectureInterval.plusWeek(1)
Thanks!
There appears to be a bug in the fix to http://sourceforge.net/p/joda-time/bugs/148 (which I also reported).
The following code (which can be added to org.joda.time.format.TestDateTimeFormatter) breaks, because the input mutable date time's millis appear to be mishandled and the year for the parse is changed to 1999:
public void testParseInto_monthDay_feb29_startOfYear() {
DateTimeFormatter f = DateTimeFormat.forPattern("M d").withLocale(Locale.UK);
MutableDateTime result = new MutableDateTime(2000, 1, 1, 0, 0, 0, 0, NEWYORK);
assertEquals(4, f.parseInto(result, "2 29", 0));
assertEquals(new MutableDateTime(2000, 2, 29, 0, 0, 0, 0, NEWYORK), result);
}
joda time displays timezone in numeric format (i.e. "+2:00") for Germany locale, but for Franch or US locale timezone displayed in verbose format (i.e. EET)
Code snippets to reproduce the issue are displayed below.
This is utility method to make pattern for conversion.
private static String getDateTimePattern(Locale locale) {
StringBuffer dateTimePattern = new StringBuffer();
dateTimePattern.append(((SimpleDateFormat) DateFormat.getDateInstance(DateFormat.MEDIUM, locale)).toPattern());
dateTimePattern.append(" ");
dateTimePattern.append(((SimpleDateFormat) DateFormat.getTimeInstance(DateFormat.SHORT, locale)).toPattern());
dateTimePattern.append(" ");
dateTimePattern.append("z");
return dateTimePattern.toString();
}
Snippet to reproduce in JUnit unit test
Date date = new Date(100000000);
Style style = Style.DATETIME;
Locale locale = Locale.GERMANY;// !!!
TimeZone zone = new SimpleTimeZone(7200000, "Asia/Amman", 2, -1, 5, 86400000, 0, 9, -1, 6, 0, 1, 3600000);
dtf = DateTimeFormat.forPattern(getDateTimePattern(locale)).withLocale(locale);
dtf = dtf.withZone(DateTimeZone.forTimeZone(timezone));
DateTime dt = new DateTime(date);
assertEquals("02.01.1970 05:46 EET", dt.toString(dtf));
Hello,
I am using JodaTime v2.3 in combination with a DB4O object database. I have noticed that when retrieving DateTime objects from the database I get NullPointerExceptions when calling: dateTimeObj.getZone().getOffset(long)
Here's a stacktrace:
Caused by: java.lang.NullPointerException
at java.util.Arrays.binarySearch(Arrays.java:827)
at org.joda.time.tz.DateTimeZoneBuilder$PrecalculatedZone.nextTransition(DateTimeZoneBuilder.java:1574)
at org.joda.time.tz.CachedDateTimeZone.createInfo(CachedDateTimeZone.java:158)
at org.joda.time.tz.CachedDateTimeZone.getInfo(CachedDateTimeZone.java:145)
at org.joda.time.tz.CachedDateTimeZone.getOffset(CachedDateTimeZone.java:103)
I believe this problem also affects JodaTime v2.2.
Best,
Matthias
DateTimeZone
does not apply a max/min value for an offset. However the parse method is limited to 23:59. Make 23:59:59.999 the maximum.
Hello,
In JRuby, we want nanosecond precision in a couple places.
The JVM only provides a millisecond precision wall-clock (but that should change with JSR 310). So of course for now we can only retain nanoseconds that are given by the user.
The logic to handle nanoseconds lives in RubyTime, the class for handling Ruby "Time" objects. I would like to extract it to some DateTime-like class handling nanoseconds (that is an additional int field). DateTime is a final class so it cannot be subclassed. Composition is of course possible but it might hurt a bit performance and it means to write every delegation method.
What would be a good way to add support for nanosecond precision to DateTime according to you?
Do you have plans for doing this in Joda-Time?
It could be a nice idea to migrate JUnit to the 4 version. It contains a lot of nice features like annotations, parameterized tests, matchers and so on
Hi.
Joda version 2.1
For reasons too weird to describe, I tried to format a LocalDate using ISODateTimeFormat.dateTimeNoMillis. The date part comes out fine, as does the subsequent 'T'. However, the time parts are rendered not as 00:00:00, but with some strange characters. It's easy to reproduce. Something like:
ISODateTimeFormat.dateTimeNoMillis.print(LocalDate.now())
should show the problem.
Repro:
DateTimeZone = DateTimeZone.forID("America/Havana");
long milli = 1352005199998;
MutableDateTime dt = new MutableDateTime(milli, timeZone);
// now dt is 2012-11-04T00:59:59.998-04:00
int year = dt.getYear(); // 2012
int month = dt.getMonthOfYear(); // 11
int day = dt.getDayOfMonth(); // 4
Interval theDay = new LocalDate(year, month, day).toInterval(timeZone);
// theDay is 2012-11-04T00:00:00.000-05:00/2012-11-05T00:00:00.000-05:00,
// which does not include dt.
Interval lastDay = new LocalDate(year, month, day-1).toInterval(timeZone);
// lastDay is 2012-11-03T00:00:00.000-04:00/2012-11-04T00:00:00.000-05:00
// i.e. joda thinks that 2012-11-04T00:59:59.998-04:00 is an instance of 2012-11-3
// instead of 2012-11-04
Cross post from: https://sourceforge.net/p/joda-time/bugs/173/
I created a simple program to display the timezone and the output of this program is incorrect in the Asia/Riyadh timezone. It returns +03:00 as the output when I run this in the Asia/Riyadh domain, but it returns "America/Chicago" when I run it on the normal US domain.
import org.joda.time.DateTimeZone;
public class timezoneclass {
public static void main(String args[])
{
System.out.println(DateTimeZone.getDefault());
}
}
OUTPUT:
+03:00
Any idea why its returning this value? I checked the user.system timezone and the JDK timezone. They look right. I didn't notice any differences between the two domains other than that they are physically in different timezones.
I am using joda-time-1.6.2.jar. I've also tried using the joda-time-2.1.jar but still the same issue. I am trying to understand where it is getting the +03:00 value from. I also checked the TZ variable and it is set to 'WAT-3'. I've changed this to 'WAT-4' but I still get a +03:00 as the output.
Is there anything else I should be looking for? Please advise!
Thank you,
Manogna
Let me start with code (I used Date
as a comparison, but anything comparable would do, like String
, Integer
, ...):
java.util.Date normalDate = new java.util.Date();
org.joda.time.DateTime jodaDate = new new org.joda.time.DateTime();
org.junit.Assert.assertThat(normalDate, org.hamcrest.Matchers.equalsTo(normalDate));
org.junit.Assert.assertThat(jodaDate, org.hamcrest.Matchers.equalsTo(jodaDate));
org.junit.Assert.assertThat(normalDate, org.hamcrest.Matchers.lessThan(normalDate));
org.junit.Assert.assertThat(jodaDate, org.hamcrest.Matchers.lessThan(jodaDate));
at the 4th assertThat
(jodaDate
/lessThan
) I get weird warning message in Eclipse:
Type safety: The expression of type
Matcher
needs unchecked conversion to conform toMatcher<? super DateTime>
My guess it is because ReadableInstant extends Comparable
and not Comparable<ReadableInstant>
.
int compareTo(Object readableInstant);
will throw a ClassCastException
if it's not instanceof ReadableInstant
which makes it pointless to implement the raw Comparable
interface.
That check can be made by the compiler at compile time. In my opinion it won't break any working code because if someone ever calls it with anything other than ReadableInstant
instance, they would get an exception anyway, which no-one wants I guess (maybe your unit tests...).
Would it be possible to change the interface extension to the generic one?
It will give a warning for anyone who tries to use it against any generic interface which expects Comparable
, which is pretty annoying if they want "warning-less" code. @SuppressWarnings
is rather pointless, hopefully I'll only have to use it at a few places. (For example equalsTo
in Hamcrest does not give a warning)
Migrated from https://sourceforge.net/p/joda-time/bugs/172/
All calculation in the method is done with long, but the parameter only accept int.
I tried:
DateTimeFormatter sigactDatetimeFormatter = DateTimeFormat.forPattern("M d");
But JodaTime throws an error:
java.lang.IllegalArgumentException: Invalid format: "January 1"
at org.joda.time.format.DateTimeFormatter.parseDateTime(DateTimeFormatter.java:873)
...
From: http://joda.sourceforge.net/api-time/org/joda/time/DateTimeConstants.html
Every one of the day constants mentions that it represents Monday. For example:
static int THURSDAY
Constant (4) representing Monday, the fourth day of the week (ISO)
static int TUESDAY
Constant (2) representing Monday, the second day of the week (ISO)
static int WEDNESDAY
Constant (3) representing Monday, the third day of the week (ISO)
Hi I wanted to let you know that the following code has 3 issues:
Period p1 = new Period(5L, PeriodType.hours());
String string = p1.toString();
System.out.println(string);
Period p2 = Period.parse(string);
System.out.println(p2);
//The expected result
Period period=Period.hours(5);
System.out.println(period);
assert p1.equals(p2);
Outputs:
PT0H
PT0S
PT5H
Exception in thread "main" java.lang.AssertionError
It seems that the Period constructor is broken.
One would expect that printing a period and then parsing it would give an identical period.
One would expect that a zero period in hours should be equal to zero seconds.
Release Joda Time 2.2
joda-time joda-time 2.2Upon DST transition from summer to winter time zone, adding the amount of zero days to a mutable date time object changes the value of the object.
The code
final MutableDateTime mdt = new MutableDateTime(2011, 10, 30, 3, 0, 0, 0, DateTimeZone.forID("Europe/Berlin"));
System.out.println("Start date: " + mdt + " (" + mdt.toInstant().getMillis() + ")");
mdt.addHours(-1);
System.out.println("addHours(-1): " + mdt + " (" + mdt.toInstant().getMillis() + ")");
mdt.addHours(0);
System.out.println("addHours(0): " + mdt + " (" + mdt.toInstant().getMillis() + ")");
mdt.addDays(0);
System.out.println("addDays(0): " + mdt + " (" + mdt.toInstant().getMillis() + ")");
prints
Start date: 2011-10-30T03:00:00.000+01:00 (1319940000000) //OK
addHours(-1): 2011-10-30T02:00:00.000+01:00 (1319936400000) //OK
addHours(0): 2011-10-30T02:00:00.000+01:00 (1319936400000) //OK, no change in time
addDays(0): 2011-10-30T02:00:00.000+02:00 (1319932800000) //error, time has changed by 1 hour
The methods addMonths and addYears show the same problem; addSeconds, addMinutes and addHours are ok.
I have tested with version 2.3. However, if I repeat the test with Joda 1.5.2, the invocation of addDays(0) does not change the date's value.
I expect the following test to pass:
Chronology chronology = GJChronology.getInstance();
LocalDate start = new LocalDate(2013, 5, 31, chronology);
LocalDate expectedEnd = new LocalDate(-1, 5, 31, chronology); // 1 BC
assertThat(start.minusYears(2013), is(equalTo(expectedEnd)));
assertThat(start.plus(Period.years(-2013)), is(equalTo(expectedEnd)));
The error it gives is:
org.joda.time.IllegalFieldValueException: Value 0 for year is not supported
However, I never provided "0" for the year myself. I thought it was the job of the framework to skip over non-existent year 0 for me to return 1 BC?
Hi, I would to use Joda Time, but I prefer to not jump JPA to hibernate direclty.
So exist the chance to have the support for JPA in the next future?
Thanks
The most common format for ISO8601 for a timestamp is this
yyyy-mm-ddTHH:MM:SS.SSS
But also a space is allowed:
yyyy-mm-dd HH:MM:SS.SSS
I would suggest you to allow the construction of a timestamp also out of the second variant. Would you please implement this for the constructor DateTime(Object instant)?
I think, that this could be easily done by adding a line like this
((String) instant).replace(' ', 'T');
I would like to have support for the following operations on Duration
:
Duration.scale(double factor)
- stretch the duration by the given factor
mul(int factor)
and div(int factor)
would also make senseDuration.floor(ReadableDuration precision)
- round the duration down to the nearest multiple of precision
Duration.ceil(ReadableDuration precision)
- round the duration up to the nearest multiple of precision
If no one objects to such operations, I would be happy to fork and implement them.
Hi,
Quick question about the output I'm seeing and I'm not sure it's a bug or not.
We are using JodaTime to convert our Calendar/Date objects into ISO8601 format to be sent along in a JSON payload.
Things work fine for most normal dates, but our QA team found an interesting issue when they use the year '0000' which is a valid year.
We are seeing that the JodaTime library seems to lose 2 days during the formatting where the JDK SimpleDateFormatters don't.
Is this a bug? Below is the sample code and output.
JODA: 0000-10-27T12:03:58.000-04:56:02
JAVA: 0001-10-29T12:00:00.000-0500
public class DateTest {
// Standard ISO8601 Date format
private static final String ISO8601 = "yyyy-MM-dd'T'hh:mm:ss.SSSZ";
/**
* Test the difference between JODA and JDK date formats when year is 0000
* @param args
*/
public static void main(String[] args) {
// Set the calendar to known state
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR, 0000);
c.set(Calendar.DAY_OF_MONTH, 29);
c.set(Calendar.MONTH, Calendar.OCTOBER);
c.set(Calendar.HOUR_OF_DAY, 12);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
Date d = c.getTime();
doJoda(d);
doJava(d);
}
/**
* Print using JODA TIME
* @param d
*/
private static void doJoda(Date d) {
System.out.println("JODA: " + new DateTime(d).toString());
}
/**
* Print using JDK
* @param d
*/
private static void doJava(Date d) {
SimpleDateFormat df = new SimpleDateFormat(ISO8601);
System.out.println("JAVA: " + df.format(d));
}
}
Thanks...
What's the point of (MutableDateTime|MutableInterval|MutablePeriod) copy methods? Why not just have clone return the specific class in question rather than Object?
(as per discussion on the joda-interest list)
The javadoc of ISODateTimeFormat class says it's thread-safe and immutable. The static fields are lazily initialized. However it seems it's not done in a thread-safe manner.
For example, dt is lazily initialized in
public static DateTimeFormatter dateTime() {
if (dt == null) {
dt = new DateTimeFormatterBuilder()
.append(date())
.append(tTime())
.toFormatter();
}
return dt;
}
When there are two threads both inside this method, is it possible that one thread sees an unsafely published non-null dt value due to cache incoherence?
The Joda Time 2.3 incorrectly converts MST TimeZone to DateTimeZone. The following test fails:
@Test
public void test() {
TimeZone jdkMST = TimeZone.getTimeZone("MST");
DateTimeZone mst = DateTimeZone.forTimeZone(jdkMST);
DateTimeZone mst2 = DateTimeZone.forID(jdkMST.getID());
assertEquals("MST", mst2.getID());
assertEquals("MST", mst.getID());
assertEquals(mst, mst2);
}
The resulting zone for MST is "America/Denver" that has daylight saving, while MST does not have daylight savings. This causes incorrect display of the time, since time zone offset of different.
Apparently the offending method is in DateTimeZone.java:
private static synchronized String getConvertedId(String id) {
Map<String, String> map = cZoneIdConversion;
if (map == null) {
// Backwards compatibility with TimeZone.
map = new HashMap<String, String>();
......
map.put("MST", "America/Denver"); // JDK 1.1 compatible
......
cZoneIdConversion = map;
}
return map.get(id);
}
It possibly contains some work around for JDK 1.1, but this workaround also applies to JDK 1.6, that contains correct definition of MST time zone. JDK 1.1 work around should be applied only when needed and not to change DateTimeZone when it is not needed.
Due to countries changing their time zone rules and having to reassemble joda-time to pick them up, it'd be beneficial to allow a system property to define an alternate location to read the time zone data files. By defining a property such as
-Dorg.joda.time.tz.data=path/to/files
the data files would be read in from the path provided; if no property was declared, it would default to its current behavior of loading the files it compiled when being packaged. This could be used as a stop-gap until a solution described in #17 could be implemented.
private static final Logger logger = LoggerFactory.getLogger(JodaTimeZoneTest.class);
private static final LocalDateTime SUMMER_TIME = LocalDateTime.parse("2013-06-25T12:00:00");
private static final LocalDateTime WINTER_TIME = LocalDateTime.parse("2012-12-25T12:00:00");
public void testTimeZone(TimeZone tz) {
DateTimeZone dtzone = DateTimeZone.forTimeZone(tz);
int winterHours = hourOfDayUTC(WINTER_TIME, dtzone);
int summerHours = hourOfDayUTC(SUMMER_TIME, dtzone);
logger.info("TZ: {}, winter hours={}, summer hours={}", new Object[]{tz, winterHours, summerHours});
assertEquals(1, Math.abs(winterHours - summerHours));
}
private int hourOfDayUTC(LocalDateTime winterTime, DateTimeZone dtzone) {
return winterTime.toDateTime(dtzone).toDateTime(DateTimeZone.UTC).getHourOfDay();
}
passes for TimeZone.getTimeZone("Europe/London") but fails for custom TZ with the same settings:
new SimpleTimeZone(3600000,
"GMT",
Calendar.MARCH, -1, Calendar.SUNDAY,
3600000, SimpleTimeZone.UTC_TIME,
Calendar.OCTOBER, -1, Calendar.SUNDAY,
3600000, SimpleTimeZone.UTC_TIME,
3600000)
DateTimeZone.forOffsetHoursMinutes(h,m)
cannot handle negative offset < 1 hour like -0:30
due to argument range checking. I used forOffsetMillis()
instead.
This should probably be mentioned in the documentation or negative minutes be accepted.
Fix cache synchronization in BuddhistChronology and GJChronology.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.