问题
I try to parse date string but always get wrong month. Here's my code.
This is code to select date from calender
@OnClick(R.id.tedit_tgllahir_addnew) void showTimeDialog(){
calendar = Calendar.getInstance();
year = calendar.get(Calendar.YEAR);
month = calendar.get(Calendar.MONTH);
date = calendar.get(Calendar.DAY_OF_MONTH);
DatePickerDialog datePickerDialog = new DatePickerDialog(AddDataForNewUserActivity.this,
new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
etTgl.setText(String.format("%02d/%02d/%02d", year, month+1, dayOfMonth));
}
}, year, month, date);
datePickerDialog.show();
}
and this is when i want to parse data
birth = LocalDate.of(list.getTglLahirAnak().getYear() + 1900, list.getTglLahirAnak().getMonth(), list.getTglLahirAnak().getDate());
int year = Period.between(birth, LocalDate.now()).getYears();
int month = Period.between(birth, LocalDate.now()).getMonths();
int totalBulan = year * 12 + month;
Whenever I input date from the calender, it always shows the wrong month. For example I choose May but in the system read April. Thanks to all who are willing to help.
回答1:
I gather from your question that you are using the backport of JSR-310, probably the Android edition, ThreeTenABP. If so, go all-in on that and drop the use of the poorly designed and long outdated Calendar
and Date
classes.
Even if the use of the Date
class is dictated from outside of your control, you must still stay away from its deprecated methods including getYear()
, getMonth()
and getDate()
. You are trying the good thing when receiving a Date
and converting it to a LocalDate
first thing. Use DateTimeUtils
from the backport for a first conversion.
But let’s take it from the top. Use LocalDate
for setting the initial date of your date picker. Don’t use the old-fashioned Calendar
class. I have not compiled the code, so please forgive if there’s a typo.
LocalDate today = LocalDate.now(ZoneId.systemDefault());
year = today.getYear();
month = today.getMonthValue(); // naturally 1-based
date = today.getDayOfMonth();
DatePickerDialog datePickerDialog = new DatePickerDialog(AddDataForNewUserActivity.this,
new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
// will return to this part later
}
}, year, month - 1, date); // Pass 0-based month
When the user selects a date from the calendar/date picker, don’t store it as a string. Store it as a LocalDate
object. This saves you from doing any parsing later, and your code also shows that you need a LocalDate
. Obviously if you want to show the selected date to the user, format the date into a string for that purpose (only). Use a DateTimeFormatter
for formatting:
private static final DateTimeFormatter dateFormatter
= DateTimeFormatter.ofPattern("yy/MM/dd");
Now we go:
@Override
public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
// Store the selected date somewhere you can find it later
selectedLocalDate = LocalDate.of(year, month + 1, dayOfMonth);
// Display to the user
String formattedDate = selectedLocalDate.format(dateFormatter);
etTgl.setText(formattedDate);
}
Now the calculation of age in months poses no problem anymore:
birth = selectedLocalDate;
long totalBulan = Period.between(birth, LocalDate.now(ZoneId.systemDefault()))
.toTotalMonths();
If you cannot control what you get from list.getTglLahirAnak()
, the conversion from Date
to LocalDate
is:
Date oldfashionedDate = list.getTglLahirAnak();
birth = DateTimeUtils.toInstant(oldfashionedDate)
.atZone(ZoneId.systemDefault())
.toLocalDate();
Now the calculation of age proceeds as before.
What went wrong in your code?
Just like the outdated Calendar
also the deprecated Date.getMonth()
numbers the months from 0 for January through 11 for December. So if you pick a date in May, list.getTglLahirAnak().getMonth()
returns 4 for May. When you feed this into a LocalDate
with its natural and sensible month numbering, it gives you April.
来源:https://stackoverflow.com/questions/63065988/parse-date-string-return-wrong-month