Unexpected Behavior using Dates in Java - java

I have the following code:
import java.util.Date;
import java.util.Calendar;
import java.text.SimpleDateFormat;
import org.junit.Test;
public class DateCalendarTest {
#Test
public void test1() {
private final DateFormat df1 = new SimpleDateFormat("MM/dd/yyyy");
String batchdt = "2015/09/23";
System.out.println("Date & Calendar Test: " + batchdt);
Calendar cal = Calendar.getInstance();
Date date1 = df1.parse(batchdt);
cal.setTime(date1);
System.out.println("Date & Calendar Test: " + cal.getTime());
}
}
Output:
Date Calendar Test: 2015/09/23
Date Calendar Test: Mon Nov 09 00:00:00 EST 190
Can someone please explain why this behaves in this manner?

Your intended data doesn't match the format specified in your SimpleDateFormat. However, by default, it is lenient in how it parses the data. For example, September 31st would be interpreted as October 1st.
Here, it's interpreted as day 9 of month 2,015 of year 23. 2,015 months is 167 years, 11 months, which when added to the year 23 yields the year 190. In this case, it is very lenient.
The output format is what is expected when printing out a Date directly.

Related

DateTime addmonths method is adding 1 extra day

I am currently working on an issue where DateTime.addMonths(iStartDateH, durationAsInt) is adding an extra day. It uses GeorgianCalendar internally.
We are using Java 5 currently in this project
Eg: For 24 months
ExpirationDate=DateTime.addMonths(currentDate, 24)
CurrentDate= 01/02/2021 (dd/mm/yyyy format)
ExpirationDate= 02/02/2023
public static ErrorCode addMonths(DateHolder dateH, int numMonths) {
try {
Calendar c = new GregorianCalendar();
c.setTime(dateH.value);
c.add(Calendar.MONTH, numMonths);
dateH.value = c.getTime();
return ErrorCode.successCN;
}
catch (Exception e) {
IlMessage msg = new IlMessage(Msg.exceptionCaughtCN, e);
IlSession.getSession().getMessageStack().push(msg);
return ErrorCode.errorCN;
}
}
I tried checking the complete date/time difference and its coming as 730.773935185185185
Please help with the same.
I am using Java 8 and I tried the code below and it worked just fine for me (for testing purposes I set the date as Feb 1 as from your example.
public static void main(String...pStrings) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
LocalDate currentDate = LocalDate.of(2021, 2, 1); //LocalDate.now();
System.out.println("Original Date -" +currentDate.format(formatter));
LocalDate newDate = currentDate.plusMonths(24);
System.out.println("updated date - " + newDate.format(formatter));
}
I received the output: -
Original Date -01/02/2021
updated date - 01/02/2023
Note that m is for minutes. For a month, you need to use M.
The implementation of your class, DateHolder seems to have a problem. There is no such problem with java.util date-time API for this requirement.
Demo:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
public class Main {
public static void main(String[] args) throws ParseException {
Calendar calendar = Calendar.getInstance();
calendar.setTime(new SimpleDateFormat("dd/MM/yyyy", Locale.ENGLISH).parse("01/02/2021"));
System.out.println(calendar.getTime());
int numMonths = 24;
calendar.add(Calendar.MONTH, numMonths);
System.out.println(calendar.getTime());
}
}
Output:
Mon Feb 01 00:00:00 GMT 2021
Wed Feb 01 00:00:00 GMT 2023

Different result in parsing datetime via calendsr or simpleDateFormatter

I now working with java 1.6 and encounter strange behaviour, may be bug, here is code:
import org.junit.Test;
import javax.xml.bind.DatatypeConverter;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class TestDate {
#Test
public void testConvert() throws Exception {
Calendar parsedCalendar = DatatypeConverter.parseDateTime("0001-01-01T00:00:00");
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
Date sdfDate = simpleDateFormat.parse("0001-01-01T00:00:00");
Calendar parsedCalendar2 = DatatypeConverter.parseDateTime("1980-03-01T00:00:00");
SimpleDateFormat simpleDateFormat2 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
Date sdfDate2 = simpleDateFormat2.parse("1980-03-01T00:00:00");
System.out.println("parsedCalendar: " + parsedCalendar.getTimeInMillis());
System.out.println("parsedCalendar TZ: " + parsedCalendar.getTimeZone());
System.out.println("parsedCalendar Date: " + parsedCalendar.getTime());
System.out.println("sdfDate: " + sdfDate);
System.out.println("sdfDate millis: " + sdfDate.getTime());
System.out.println("parsedCalendar2: " + parsedCalendar2.getTimeInMillis());
System.out.println("parsedCalendar2 TZ: " + parsedCalendar2.getTimeZone());
System.out.println("parsedCalendar2 Date: " + parsedCalendar2.getTime());
System.out.println("sdfDate2: " + sdfDate2);
System.out.println("sdfDate2 millis: " + sdfDate2.getTime());
}
}
And here is problem:
OUTPUT:
parsedCalendar: -62135622000000
parsedCalendar TZ: sun.util.calendar.ZoneInfo[id="Asia/Novosibirsk",offset=25200000,dstSavings=0,useDaylight=false,transitions=67,lastRule=null]
parsedCalendar Date: Mon Jan 03 00:00:00 NOVT 1
sdfDate: Sat Jan 01 00:00:00 NOVT 1
sdfDate millis: -62135794800000
parsedCalendar2: 320691600000
parsedCalendar2 TZ: sun.util.calendar.ZoneInfo[id="Asia/Novosibirsk",offset=25200000,dstSavings=0,useDaylight=false,transitions=67,lastRule=null]
parsedCalendar2 Date: Sat Mar 01 00:00:00 NOVT 1980
sdfDate2: Sat Mar 01 00:00:00 NOVT 1980
sdfDate2 millis: 320691600000
DEBUG:
parsedCalendar.getTimeInMillis() = -62135622000000
sdfDate.getTime() = -62135794800000
parsedCalendar.getTime() = {Date#790} "Mon Jan 03 00:00:00 NOVT 1"
sdfDate = {Date#759} "Sat Jan 01 00:00:00 NOVT 1"
parsedCalendar2.getTimeInMillis() = 320691600000
sdfDate2.getTime() = 320691600000
parsedCalendar2.getTimeZone() = {ZoneInfo#755} "sun.util.calendar.ZoneInfo[id="Asia/Novosibirsk",offset=25200000,dstSavings=0,useDaylight=false,transitions=67,lastRule=null]"
parsedCalendar.getTimeZone() = {ZoneInfo#756} "sun.util.calendar.ZoneInfo[id="Asia/Novosibirsk",offset=25200000,dstSavings=0,useDaylight=false,transitions=67,lastRule=null]"
simpleDateFormat.getTimeZone() = {ZoneInfo#757} "sun.util.calendar.ZoneInfo[id="Asia/Novosibirsk",offset=25200000,dstSavings=0,useDaylight=false,transitions=67,lastRule=null]"
simpleDateFormat2.getTimeZone() = {ZoneInfo#758} "sun.util.calendar.ZoneInfo[id="Asia/Novosibirsk",offset=25200000,dstSavings=0,useDaylight=false,transitions=67,lastRule=null]"
As you can see in parsing 0001 dateTime there is difference in ms! And in parsing 1980 it is not.
Who can explain why?
This is due to the difference between the Julian and Gregorian calendar systems.
SimpleDateFormat uses the default calendar system, which I believe to be GregorianCalendar on both your system and mine. GregorianCalendar (despite its name) switches between the Gregorian calendar system and the Julian calendar system, based on the gregorianChange property. It assumes that any date provided after that cut-over is Gregorian, and any before it is Julian. The default cut-over is in 1582.
DatatypeConverter uses a pure proleptic Gregorian calendar instead, as that's what the W3C XML Schema docs require.
That means if you parse a value just before the calendar switch, you'll see a large difference - and that difference will get smaller as you go further back in time, with a difference of 3 days every 400 years. (The three century-years which aren't divisible by 400, and so are leap years in the Julian calendar but not in the Gregorian calendar.)
If you set the calendar in the SimpleDateFormat to a GregorianCalendar which you've called setGregorianChange(Long.MIN_VALUE) on first, the two will agree.
Here's code to make it easier to explore the difference:
import javax.xml.bind.DatatypeConverter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.TimeUnit;
public class Test {
public static void main(String[] args) throws ParseException {
convert("0001-01-01T00:00:00");
convert("1000-01-01T00:00:00");
convert("1580-01-01T00:00:00");
convert("1590-01-01T00:00:00");
convert("1980-03-01T00:00:00");
}
private static void convert(String input) throws ParseException {
Calendar datatypeConverterResult = DatatypeConverter.parseDateTime(input);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
Date sdfResult = simpleDateFormat.parse(input);
System.out.println("Input: " + input);
long datatypeConverterMillis = datatypeConverterResult.getTimeInMillis();
long sdfResultMillis = sdfResult.getTime();
long days = TimeUnit.MILLISECONDS.toDays(datatypeConverterMillis - sdfResultMillis);
System.out.println("DatatypeConverter epoch millis: " + datatypeConverterMillis);
System.out.println("SimpleDateTime epoch millis: " + sdfResultMillis);
System.out.println("Difference in days: " + days);
System.out.println("Parsed calendar time zone: " + datatypeConverterResult.getTimeZone().getID());
System.out.println();
}
}
Note that on Java 9, you need to specify the module explicitly. This is simplest done with java.se.ee:
$ javac Test.java --add-modules java.se.ee
$ java --add-modules java.se.ee Test
Output on my box:
Input: 0001-01-01T00:00:00
DatatypeConverter epoch millis: -62135596800000
SimpleDateTime epoch millis: -62135769600000
Difference in days: 2
Parsed calendar time zone: Europe/London
Input: 1000-01-01T00:00:00
DatatypeConverter epoch millis: -30610224000000
SimpleDateTime epoch millis: -30609792000000
Difference in days: -5
Parsed calendar time zone: Europe/London
Input: 1580-01-01T00:00:00
DatatypeConverter epoch millis: -12307248000000
SimpleDateTime epoch millis: -12306384000000
Difference in days: -10
Parsed calendar time zone: Europe/London
Input: 1590-01-01T00:00:00
DatatypeConverter epoch millis: -11991628800000
SimpleDateTime epoch millis: -11991628800000
Difference in days: 0
Parsed calendar time zone: Europe/London
Input: 1980-03-01T00:00:00
DatatypeConverter epoch millis: 320716800000
SimpleDateTime epoch millis: 320716800000
Difference in days: 0
Parsed calendar time zone: Europe/London

Java Date vs Gregorian Calendar / 48h difference? [duplicate]

This question already has answers here:
Date change when converting from XMLGregorianCalendar to Calendar
(2 answers)
Closed 5 years ago.
I had a curious situation at work, where an application sent us XML containing the value "0001-01-01", which was parsed into an instance of XmlGregorianCalendar. I then realized, the value magically converted into "0001-01-03", the exact amount of 2 days was added.
This happened during the conversion from GregorianCalendar to Date, which I reproduced as followed:
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.GregorianCalendar;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
public class Test {
public static void main(String[] args) throws ParseException, DatatypeConfigurationException {
final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
GregorianCalendar gregCalendar = new GregorianCalendar();
gregCalendar.setTime(dateFormat.parse("0001-01-01"));
XMLGregorianCalendar calendar = DatatypeFactory.newInstance().newXMLGregorianCalendar(gregCalendar);
System.out.println("calendar: " + calendar);
System.out.println("date: " + calendar.toGregorianCalendar().getTime());
}
}
Sample output:
calendar: 0001-01-01T00:00:00.000Zdate: Mon Jan 03 00:00:00 GMT 1
The milliseconds differ by the exact amount of 172800000. Does anybody know why?
Cute isn't it? The Java GregorianCalendar is not a proleptic Gregorian Calendar (despite its misleading name) but a composite calendar consisting of a Julian beginning and Gregorian end. (You can even set the cutover date yourself.)
In the Gregorian Calendar, January 1, 0001 is a Monday.
In the Julian Calendar, January 1, 0001 is a Saturday.
And there, my friends, is the difference of two days.
References:
https://www.timeanddate.com/calendar/?year=1&country=22
https://www.timeanddate.com/calendar/?year=1&country=23
https://en.wikipedia.org/wiki/Adoption_of_the_Gregorian_calendar
https://docs.oracle.com/javase/7/docs/api/java/util/GregorianCalendar.html
See SetGregorianChange in the final link in particular.

java date parsing not working working for month [duplicate]

This question already has answers here:
String to Date conversion returning wrong value
(5 answers)
Closed 5 years ago.
I am trying to find the difference between two dates and I did the following:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class test {
public static void main(String[] args) {
Date date = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-DD");
String accessioned = "2017-04-27";
System.out.println(date);
try {
date = format.parse(accessioned);
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println(date);
Date now = new Date();
long diff = now.getTime() - date.getTime();
System.out.println(diff);
if ((diff / (1000 * 60 * 60 * 24)) >= 30) {
System.out.println("haha");
}
}
}
This is the output I get:
Fri Jul 21 14:23:59 CEST 2017
Fri Jan 27 00:00:00 CET 2017
15168239705
haha
The Problem is if I change the the String accessioned for e.g to "2017-04-28" the date changes accordingly, same thing for year but whatever value I put for month, It always outputs January. For e.g in my code it should be April but the output says Jan.
What am I doing wrong?
Change D to d (SimpleDateFormat Doc):
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
D is for day in year (1-365)
d is for day in month (1-31)
Also you can now use LocalDate from Java8 more convenient to use DateTimeFormatter Doc / LocalDate Doc
You apparently want to check if the difference of days is >=30 between your date and now or not, so I'll propose another solution with LocalDate :
LocalDate localDate = LocalDate.parse("2017-04-27", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
long daysDiff = localDate.until(LocalDate.now(), ChronoUnit.DAYS);
System.out.println(daysDiff);
if (daysDiff >= 30){
System.out.println("haha");
}
EDIT : You need to use LocalDateTime instead of LocalDate to be able to use hour/minute/sec also
LocalDateTime localDateTime = LocalDateTime.parse("2017-04-21T11:51:36Z", DateTimeFormatter.ISO_DATE_TIME);
The problem is your date format: new SimpleDateFormat("yyyy-MM-DD")
As listed here, M is already a two-digit format - and D stands for "Day in year", not "Day in month", which is d.
Your format should look like this:
SimpleDateFormat("y-M-d")
...which gives me:
Fri Jul 21 14:44:03 CEST 2017
Thu Apr 27 00:00:00 CEST 2017
7397043764
haha

DST Handling In Java 5 For Corner Dates

According to the following website daylight saving time in UK starts from 27 Mar-2016 1:00:00 (24 hours time format)
http://www.timeanddate.com/time/change/uk/london?year=2016
Then why the following code prints false?
import java.text.ParseException;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;
public class BSTGMTDetector
{
public static void main(String[] args) throws ParseException
{
TimeZone def = TimeZone.getTimeZone("Europe/London");
Calendar cal = new GregorianCalendar();
cal.clear();
cal.set(2016, 2, 27,2,01,01);
boolean isInDaylight = def.inDaylightTime(cal.getTime());
System.out.println("Date[" + cal.getTime() + "] is in DST[" + isInDaylight + "]");
}
}
Output : Date[Sun Mar 27 02:01:01 IST 2016] is in DST[false]
It seems that your system maintain IST.When you define,
Calendar cal = new GregorianCalendar();
Timezone for cal variable is IST.So,when call
def.inDaylightTime(cal.getTime());
Date is passed to this method in IST timezone.So,DST start for UK at 27th MAR,06:30:00 IST.
Hence.your O/P behaviour.

Categories

Resources