解析日期字符串返回错误的月份。

huangapple go评论70阅读模式
英文:

Parse Date String Return Wrong Month

问题

以下是翻译好的内容:

我尝试解析日期字符串,但始终得到错误的月份。以下是我的代码。

这是从日历中选择日期的代码

@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();
    }

以下是在我想要解析数据时的代码

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;

无论我从日历中输入日期,它总是显示错误的月份。例如,我选择了五月,但系统读取为四月。感谢所有愿意帮助的人。

英文:

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

得分: 1

我从你的问题中了解到你正在使用JSR-310的后移版本,可能是Android版的ThreeTenABP。如果是这样,请完全采用它,并放弃使用设计不佳且过时的CalendarDate类。

即使使用Date类是由于你无法控制的外部原因,你仍必须避免使用其中的弃用方法,包括getYear()getMonth()getDate()。当接收到一个Date并将其转换为LocalDate时,你正在尝试正确的事情。首先使用后移版本中的DateTimeUtils进行转换。

但让我们从头开始。在设置日期选择器的初始日期时,请使用LocalDate,而不要使用老式的Calendar类。我没有编译代码,所以如果有错别字,请谅解。

LocalDate today = LocalDate.now(ZoneId.systemDefault());
year = today.getYear();
month = today.getMonthValue(); // 自然上从1开始
date = today.getDayOfMonth();
DatePickerDialog datePickerDialog = new DatePickerDialog(AddDataForNewUserActivity.this,
    new DatePickerDialog.OnDateSetListener() {
        @Override
        public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
            // 以后再回到这部分
        }
    }, year, month - 1, date); // 传递基于0的月份

当用户从日历/日期选择器中选择日期时,请不要将其存储为字符串。将其存储为LocalDate对象。这样可以避免以后进行任何解析,并且你的代码还显示出你需要一个LocalDate。显然,如果你想向用户显示所选日期,请将日期格式化为字符串(仅限此目的)。使用DateTimeFormatter进行格式化:

private static final DateTimeFormatter dateFormatter
    = DateTimeFormatter.ofPattern("yy/MM/dd");

现在我们继续:

@Override
public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
    // 将所选日期存储在稍后可以找到的位置
    selectedLocalDate = LocalDate.of(year, month + 1, dayOfMonth);
    // 显示给用户
    String formattedDate = selectedLocalDate.format(dateFormatter);
    etTgl.setText(formattedDate);
}

现在,计算月龄不再有问题:

birth = selectedLocalDate;
long totalBulan = Period.between(birth, LocalDate.now(ZoneId.systemDefault()))
                       .toTotalMonths();

如果你无法控制从list.getTglLahirAnak()获取的内容,从Date转换为LocalDate的方法如下:

Date oldfashionedDate = list.getTglLahirAnak();
birth = DateTimeUtils.toInstant(oldfashionedDate)
    .atZone(ZoneId.systemDefault())
    .toLocalDate();

现在,年龄的计算与之前一样进行。

你的代码出了什么问题?

就像过时的Calendar一样,被弃用的Date.getMonth()将月份从0表示,从1代表一月到11代表十二月。因此,如果你选择了五月的一个日期,list.getTglLahirAnak().getMonth()会返回4,表示五月。当你将这个值传递给LocalDate,它以自然且合理的月份编号,会得到四月。

英文:

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.

huangapple
  • 本文由 发表于 2020年7月24日 10:46:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/63065988.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定