日历不会 return 与 AM/PM 约会

Calendar won't return date with AM/PM

我想要 AM/PM 格式的日期。示例建议将 SimpleDateFormat 与 a 或 aa 一起使用,但这对我来说根本不起作用。

首先我定下了日期。然后我将视图设置为开始时间可见。

结果是 Wed May 20 的格式 01:00:00 EDT 2020 想要类似 Wed May 20 的格式 01:00:00 AM EDT 2020

这适用于 setStartTime 方法中的 calendar.getTime()。第一种方法之所以被包括在内,是因为所选日期作为全局变量链接。问题在于第二种方法。

我可能可以手动将最终日期更改为字符串并将其转换回来,但我不想增加不必要的复杂性。我想找出为什么 Calendar 不会成功,因为这应该是非常基本的。

最后我的目标是将日期添加到 firebase。它必须在 Android、IOS 和 Web 中统一。因此,我需要日期采用这种精确格式。

代码如下:

    SimpleDateFormat serviceSETimeFormat = new SimpleDateFormat("MMM dd, yyyy HH:mm aa");

public void setStartDay(View view)
{
    Calendar calendar = Calendar.getInstance();
    DatePickerDialog picker = new DatePickerDialog(ServiceCreation.this,
        new DatePickerDialog.OnDateSetListener() {
            @Override
            public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
                GregorianCalendar mCal = new GregorianCalendar(year, monthOfYear, dayOfMonth);
                Date dateForDisplay = mCal.getTime();
                int startHourIndex = getThirdSpaceIndex(dateForDisplay.toString());
                //SimpleDateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy");
                serviceSETimeFormat.setCalendar(mCal);
                Date dateFormatted = null;
                try{
                    dateFormatted= serviceSETimeFormat.parse(serviceSETimeFormat.format(mCal.getTime()));
                    currBaseStartDate=dateFormatted;
                }
                catch(ParseException p){
                    Log.wtf("SC","Parse exc34");
                }
                Log.wtf("SC","Here is orig date: "+dateFormatted);
                //Don't show hh/mm/ss (these are held as 0)
                startDayView.setText(dateForDisplay.toString().substring(0,startHourIndex));
                startEndTimeWrapper.setVisibility(View.VISIBLE);
            }
        }, calendar.get(Calendar.YEAR),calendar.get(Calendar.MONTH),calendar.get(Calendar.DAY_OF_MONTH));
    long currentTime = new Date().getTime();
    picker.getDatePicker().setMinDate(currentTime);
    picker.show();
}


public void setStartTime(View view) {
    TimePickerDialog mTimePicker = new TimePickerDialog(ServiceCreation.this,
        android.R.style.Theme_Holo_Light_Dialog_NoActionBar, new TimePickerDialog.OnTimeSetListener() {
        @Override
        public void onTimeSet(TimePicker timePicker, int selectedHour, int selectedMinute) {
            String minuteAsS =  Integer.toString(selectedMinute);
            if(minuteAsS.length()==1){
                minuteAsS="0"+minuteAsS;
            }
            if(selectedHour==0){
                startTimeView.setText((selectedHour+12)+":"+minuteAsS+" AM");
            }
            else if(selectedHour<12){
                startTimeView.setText(selectedHour+":"+minuteAsS+" AM");
            }
            else if(selectedHour==12){
                startTimeView.setText((selectedHour)+":"+minuteAsS+" PM");
            }
            else{
                startTimeView.setText((selectedHour-12)+":"+minuteAsS+" PM");
            }

            (findViewById(R.id.endTimeWrapper)).setVisibility(View.VISIBLE);
            Calendar calendar = new GregorianCalendar();
            calendar.setTime(currBaseStartDate);
            calendar.set(Calendar.MINUTE, selectedMinute);
            Log.wtf("SC","Hour before condition: "+selectedHour);
            if(selectedHour>=12){
                if(selectedHour!=12){
                    Log.wtf("SC","Decrementing hour");
                    selectedHour-=12;
                }
                Log.wtf("SC","Hour set: "+selectedHour);
                calendar.set(Calendar.AM_PM,Calendar.PM);
                calendar.set(Calendar.HOUR_OF_DAY,selectedHour);
            }
            else{
                calendar.set(Calendar.AM_PM,Calendar.AM);
                calendar.set(Calendar.HOUR_OF_DAY,selectedHour);
            }
            startTime=calendar.getTime();
            Log.wtf("SC","Here is orig start time: "+startTime);
            try{
                startTime=serviceSETimeFormat.parse(serviceSETimeFormat.format(startTime));
                Log.wtf("SC","Here is parsed start time: "+startTime);
            }
            catch(ParseException e){
                Log.wtf("SC","START DATE PARSE EXCEPTION");
            }
        }
    }, 12, 0, false);
    mTimePicker.setTitle("Select Start Time: ");
    mTimePicker.show();
}

三分:

  1. 即使在 Android 甚至 API 级别,26 岁以下的人也可以考虑使用 java.time,现代 Java 日期和时间 API。 CalendarGregorianCalendarSimpleDateFormatDate 令人困惑、设计不佳且早已过时 classes。现代 API 更好用。
  2. 您不想要 CalendarDate 上午或下午。您希望将模型和呈现给用户的内容分开。在模型中,您需要一个 LocalDateTime 或其他合适的日期时间对象,并且您不想担心它的格式,无论它使用 12 小时制还是 24 小时制。为了向您的用户显示,您需要在 字符串 中以适合您的用户的格式显示日期和时间,包括 AM 或 PM。这也是为什么您的视图有 setText 方法而没有 setDate 方法的原因。
  3. Date 格式 AM/PM 不能存在。你在问不可能的事情。

java.time 和 ThreeTenABP

从年、月、日的三个整数构造一个 LocalDate 对象:

    int year = 2020;
    int monthOfYear = Calendar.MAY; // Don’t use Calendar, though
    int dayOfMonth = 11;

    LocalDate date = LocalDate.of(year, monthOfYear + 1, dayOfMonth);
    System.out.println(date);

输出:

2020-05-11

我相信您的日期选择器从 1 月的 0 到 12 月的 11 为月份编号。所以我们需要将月份数字加 1 以转换为人类和 LocalDate 数字月份的方式。我只使用 Calendar class 中的常量将变量初始化为从 0 开始的月份数字,不要在代码中这样做,因为该值来自数据选择器。 Calendar 使用相同的疯狂编号。

要将日期显示回用户,请使用格式化程序将其格式化为字符串:

    DateTimeFormatter dateFormatter = DateTimeFormatter
            .ofLocalizedDate(FormatStyle.MEDIUM)
            .withLocale(Locale.US);
    String dateForDisplay = date.format(dateFormatter);
    System.out.println(dateForDisplay);

May 11, 2020

提供适当的语言环境,或忽略对 withLocale() 的调用以依赖于设备的语言环境设置。

当用户选择时间:

    int selectedHour = 1;
    int selectedMinute = 0;

    LocalTime selectedTime = LocalTime.of(selectedHour, selectedMinute);
    LocalDateTime dateTime = date.atTime(selectedTime);
    System.out.println(dateTime);

2020-05-11T01:00

时间的格式可以与我们对日期所做的非常相似:

    DateTimeFormatter timeFormatter = DateTimeFormatter
            .ofLocalizedTime(FormatStyle.MEDIUM)
            .withLocale(Locale.US);
    String timeForDisplay = selectedTime.format(timeFormatter);
    System.out.println(timeForDisplay);

1:00:00 AM

问题:java.time 不需要 Android API 26 级吗?

java.time 在新旧 Android 设备上都能很好地工作。它只需要至少 Java 6.

  • 在 Java 8 和更新的 Android 设备上(从 API 级别 26)内置了现代 API。
  • 在非 Android Java 6 和 7 中获取 ThreeTen Backport,现代 classes 的 backport(ThreeTen 用于 JSR 310;请参阅底部的链接) .
  • 在(较旧的)Android 使用 ThreeTen Backport 的 Android 版本。它叫做 ThreeTenABP。并确保使用子包从 org.threeten.bp 导入日期和时间 classes。

链接