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.
Related
This question already has answers here:
How to merge java.sql.Date and java.sql.Time to java.util.Date?
(3 answers)
Merge java.util.date with java.sql.Time
(7 answers)
Closed 2 years ago.
Using java Calendar how can you combine the start date, day and starttime?
For example:
If the start date is 9/8/2020. The day is 2 and the start time is 8:00 AM then how can we obtain a java date that is 9/9/2020 8:00 AM. Here is my unsuccessful attempt.
def startDateTime(Date startDate, int day, java.sql.Time startTime){
def date
date = Calendar.getInstance()
date.setTime(startDate)
//adding day. since day 1 is the first day we need to add day - 1
date.add(Calendar.DATE, day - 1)
// setting the time from startTime
date.setTimeInMillis(startTime.getTime())
return date.getTime()
}
Thanks for the help.
You are calling date.setTime(startDate) and date.setTimeInMillis(startTime.getTime()). 2nd method is overriding the time set in 1st method. You should create 2 separate instances of Calendar.
Here is how you can achieve this
Create separate Calendar instances for startDay and startTime
Construct a new Calendar object from separate Calendar objects created in #1 & add day as per requirement
Here is the complete code:
import java.sql.Time;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Calendar;
import java.util.Date;
public class ProofOfConcept {
public static void main(String[] args) {
int day = 2;
Time startTime = new Time(1, 1, 1);
Calendar timeCalendar = Calendar.getInstance();
timeCalendar.setTime(startTime);
Date startDate = new Date();
Calendar startDateCalendar = Calendar.getInstance();
startDateCalendar.setTime(startDate);
/* Only java 8 and above
LocalDateTime localDateTime = LocalDateTime.of(startDateCalendar.get(Calendar.YEAR), startDateCalendar.get(Calendar.MONTH) + 1, startDateCalendar.get(Calendar.DAY_OF_MONTH),
timeCalendar.get(Calendar.HOUR), timeCalendar.get(Calendar.MINUTE), timeCalendar.get(Calendar.SECOND));
localDateTime = localDateTime.plusDays(day);
System.out.println("localDateTime : " + localDateTime);
Date dateFromLocalDateTime = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
System.out.println("dateFromLocalDateTime : " + dateFromLocalDateTime);*/
Calendar result = Calendar.getInstance();
result.set(startDateCalendar.get(Calendar.YEAR), startDateCalendar.get(Calendar.MONTH), startDateCalendar.get(Calendar.DAY_OF_MONTH) + 2,
timeCalendar.get(Calendar.HOUR), timeCalendar.get(Calendar.MINUTE), timeCalendar.get(Calendar.SECOND));
Date date = result.getTime();
System.out.println("date : " + date);
}
}
Output:
date : Tue Sep 08 01:01:01 IST 2020
Note : I suggest using java.time.* packages over java.util.*. Why? Check this. But this is only available in java 8. (Though, you can use joda time in versions below 8).
Edit : Moving Ole V.V. 's comment to answer.
For Java 7, I suggest using java.time, the modern Java date and time API, through the backport, ThreeTen Backport.
static LocalDateTime startDateTime(Date startDate, int day, java.sql.Time startTime) {
LocalTime startLocalTime = DateTimeUtils.toLocalTime(startTime);
return DateTimeUtils.toInstant(startDate)
.atZone(ZoneId.systemDefault())
.toLocalDate()
.plusDays(day - 1)
.atTime(startLocalTime);
}
When I run the following code snippet:
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;
public class TimestampTest {
public static void main(String... args) throws Exception {
Date aDate1880 = new Date(-20, 0, 1);
Timestamp timestamp = new Timestamp(aDate1880.getTime());
DateTime dateTime = new DateTime(timestamp).withZoneRetainFields(DateTimeZone.getDefault());
System.out.println(dateTime.year().get());
Calendar calendar = Calendar.getInstance();
calendar.setTime(timestamp);
System.out.println(calendar.get(Calendar.YEAR));
}
}
I get the following output:
1879
1880
As aDate1880 does actually represents year 1880 I don't know why Joda DateTime gives year as 1879. Any help would be appreciated.
This code:
Date aDate1880 = new Date(-20, 0, 1);
Creates a Date equivalent to January 1st 1880. As the time fields were not provided, they are set to midnight at the JVM default timezone. In my case, it's "America/Sao_Paulo", so the results below might be different in your case - but it'd explain what's happening anyway. In my case, the date created is:
Thu Jan 01 00:00:00 BRT 1880
(January 1st 1880 at midnight in America/Sao_Paulo timezone - BRT means "Brazilian Time")
Calling aDate1880.getTime() returns the value -2840130000000, which corresponds in UTC to 1880-01-01T03:00:00Z.
When converting to DateTime, it uses joda-time internal timezone data, an in my case the DateTime is:
1879-12-31T23:53:32.000-03:06:28
That's because before 1900, many countries didn't use current timezone rules, and most cities had their own local time. And most offsets were calculated based on the longitude, and that's why it has such strange results like "-03:06:28".
Probably your timezone has a similar issue.
Note: new DateTime(timestamp) already uses the default timezone, so the call to withZoneRetainFiels is redundant:
DateTime dateTime = new DateTime(timestamp);
// this prints "true"
System.out.println(dateTime.equals(dateTime.withZoneRetainFields(DateTimeZone.getDefault())));
To create the date you want, you can use only Joda-Time classes:
// January 1st 1880, at midnight in JVM default timezone
DateTime d = new LocalDate(1880, 1, 1).toDateTimeAtStartOfDay();
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.
this is my first time asking, I couldn't find explanation in all internet, so here you go:
I'm writing a simple function to calculate the date that was x days ago, so I wrote this code that was working very ok, until today, the calculated past date was 1 year in the future, but not for all the values, only 11 days ago, the rest was ok.
If you execute this code today you'll have this output: you can execute it here
difference:-11
2015-12-28
difference:-12
2014-12-27
As you can see, I though it was an issue parsing from Calendar to Date, also I've check that in Calendar the values were totally ok, but the moment I transfer to Date it doesn't work, I tried to do this cast manually but the functions are deprecated.
import java.util.*;
import java.lang.*;
import java.io.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
System.out.println(getDate(-11, "YYYY-MM-dd"));
System.out.println(getDate(-12, "YYYY-MM-dd"));
}
public static String getDate(int offset, String SimpleFormat) {
DateFormat dateFormat = new SimpleDateFormat(SimpleFormat);
Calendar cal = Calendar.getInstance();
cal.setTime(new Date());
cal.add(Calendar.DATE, offset);
Date todate1 = cal.getTime();
long diff = todate1.getTime()-(new Date()).getTime();
System.out.println("difference:"+diff/ (24 * 60 * 60 * 1000));
String fromdate = dateFormat.format(todate1);
return fromdate;
}
}
Later I found a nice library called Joda-Time very nice and fast, so I changed the code to work with it, but surprise the same issue.
DateFormat dateFormat = new SimpleDateFormat(SimpleFormat);
DateTime today = new DateTime();
String fromdate = dateFormat.format(today.plus(Period.days(offset)).toDate());
So far I've also check that adding 350 days or so, into this 11 days period it gives a wrong date too.
I know I can use Joda-time formatter, but still I can't find exactly what's the problem, any help would be nice :)
(for the ones who ever had this issue):
DateTimeFormatter fmt = DateTimeFormat.forPattern(SimpleFormat);
The problem isn't with the Date or DateTime, but rather with the formatter.
YYYY means the ISO Week Year. However, the ISO Week year for the last partial week of the year is the next year.
yyyy means the calendar year, which is what you really wanted.
I have a website which supplies date in 2 formats: 28th June 2009 or June 2009.
Now I would like to convert both of these into the same format yyyy-mm-dd hh:mm:ss using MySQL and Java.
SimpleDateFormat gives an error: "Unparsable Date". What's the solution?
What about June 2009 as you can not say its a date you need to make it a date by adding a day in this month-year format. Ex.. add first day of month here and make it 1 June 2009 then parse it in desired format.
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Test {
public static void main(String[] args) throws IOException, ParseException
{
String dateStr = "28 June 2009";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
System.out.println(sdf.format(new Date(dateStr)));
}
}