简体   繁体   中英

Java Date from long returning incorrect day

I am writing an Android app, and it uses the DatePicker. The date is returned in the form year, monthOfYear, dayOfMonth.

From there I can format the date as so:

            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            try {
                Date d = format.parse(year + "-" + (monthOfYear + 1) + "-" + dayOfMonth);
                String dString = d.toString().substring(0, 10) + " " +  year;
                if(startEnd) {
                    startDateText.setText(dString);
                    startDate = new Date(year, monthOfYear, dayOfMonth);
                    Log.d("Start date set- ", startDate.toString());
                } else {
                    endDateText.setText(dString);
                    endDate = new Date(year, monthOfYear, dayOfMonth);
                    Log.d("End date set- ", endDate.toString());
                }

            } catch (ParseException e) {
                Log.d("Exception- ", e.getMessage());
            }

The if(startEnd) part is just referencing two different textviews, as a range of dates is being collected.

At this point the data goes wrong. The values returned are correct. For example when I select Saturday, January 2nd the values I get are 2016 1 2, year month day.

The value of dString is also correct, it ends up as Sat Jan 02 2016.

However, when I call startDate.toString(), the value returned is Sun Jan 02 00:00:00 GMT+00:00 3916 which is a day off.

This happens on every date, and I don't know why.

The long values of startDate and endDate are passed back through setResult() as they are to be used elsewhere. Dates produced from these long values all produce the same one day off date.

Thanks in advance for any help

If you check out the Date javadoc you'll see that the constructor that you're calling requires the year-1900 . So for 2016 you would provide 116 as the year:

new Date( 116, 0, 2 );

Further, month needs to be specified 0 indexed. So January is 0 not 1 .

I should also note that it's a deprecated constructor. You should prefer Calendar.set(year + 1900, month, date) or GregorianCalendar(year + 1900, month, date) .

The accepted Answer by ulmangt is correct. But there is a vastly simpler and easier way.

Avoid Old Date-Time Classes

The old date-time classes bundled with the earliest versions of Java are notoriously troublesome. Avoid them.

Instead, use the Joda-Time library; simply add a jar to your project. In Java 8 and later, use the built-in java.time framework (inspired by Joda-Time).

LocalDate

Both Joda-Time and java.time have a LocalDate class to represent a date-only value without a time-of-day and without a time zone.

The code in the Question is trying to use a date-time value as a date-only value. This gets complicated fast as the date-time is UTC. When applying a local time zone the date may turn out to be different.

If you have a String in the format of "yyyy-MM-dd", that complies with the ISO 8601 standard. That standard is used by default in both Joda-Time and java.time for parsing/generating String representations of date-time values. So no need to specify a parsing pattern.

Some Joda-Time code.

LocalDate localDate = LocalDate.parse( "2016-01-02" );

Or you can pass integers for year, month, and day-of-month.

LocalDate localDate = new LocalDate( 2016 , 1 , 2 );

The toString method uses the same ISO 8601 format by default. You may specify other formats when generating Strings by using DateTimeFormat and DateTimeFormatter . Search StackOverflow for many examples.

You may interrogate the LocalDate for the year, month, and day-of-month numbers if needed for your user-interface.

int year = localDate.getYear();
int monthOfYear = localDate.getMonthOfYear();
int dayOfMonth = localDate.getDayOfMonth();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM