被Android中的Calendar类set()方法混淆

时间:2018-11-29 09:28:23

标签: java android android-pendingintent android-calendar

 Calendar cal = Calendar.getInstance();
            cal.set(Calendar.YEAR,Integer.parseInt(YYYY));
            cal.set(Calendar.MONTH, Integer.parseInt(MM));
            cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(DD));
            cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(hh));
            cal.set(Calendar.MINUTE, Integer.parseInt(mm));
            cal.set(Calendar.SECOND,00);
            SimpleDateFormat simpledateformat = new SimpleDateFormat("dd-MM-yyyy hh:mm");
             EditText check = (EditText) findViewById(R.id.check);
             check.setText(simpledateformat.format(cal.getTime()));

这是我为AlarmManager设置时间以在2018年11月28日下午2点56分发送意图的方法,但是一旦我单击发送按钮,它就会发送意图。

意图代码

Intent sendIntent = getPackageManager().getLaunchIntentForPackage("com.whatsapp");
            try {
                PendingIntent pendingIntent = PendingIntent.getActivity(MainActivity.this,0,sendIntent,PendingIntent.FLAG_ONE_SHOT);
                ((AlarmManager) getSystemService(ALARM_SERVICE)).setExact(AlarmManager.RTC_WAKEUP,cal.getTimeInMillis(),pendingIntent);
            }
            catch (android.content.ActivityNotFoundException ex) {
                Toast.makeText(MainActivity.this,"Please Install Whatsapp Messenger", Toast.LENGTH_LONG).show();
            }

时区是UTC + 5:30。

我设置过去的时间以及如何更正时间?

编辑:我使用了一个edittext来显示时间,并且2018年11月29日变成15-06-0211。如何?

编辑:也许这是错误的。

 EditText date = (EditText) findViewById(R.id.date);
            String dd = date.getText().toString();

            char c[] = dd.toCharArray();
            String YYYY = c[6]+c[7]+c[8]+c[9]+"";
            String MM = c[3]+c[4]+"";
            String DD =c[0]+c[1]+"";

答案-使用子字符串方法。但是我想知道为什么上述方法是错误的?

2 个答案:

答案 0 :(得分:2)

您从EditText中提取了错误的值。
首先将格式更改为:

"dd-MM-yyyy hh:mm"

"dd-MM-yyyy HH:mm"

因为您的格式使用12小时制而不是24小时制。
然后使用以下值:

String DD = dd.substring(0, 2);
String MM = dd.substring(3, 5);
String YYYY = dd.substring(6, 10);
String hh = dd.substring(11, 13);
String mm = dd.substring(14, 16);

答案 1 :(得分:2)

java.time

    DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("dd-MM-uuuu");
    DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("h:mm a");
    ZoneId zone = ZoneId.of("Asia/Kolkata");

    String dateString = "29-11-2018";
    String timeString = "2:56 PM";
    LocalDate alarmDate = LocalDate.parse(dateString, dateFormatter);
    LocalTime alarmTime = LocalTime.parse(timeString, timeFormatter);
    long triggerAlarmAtMillis = alarmDate.atTime(alarmTime)
            .atZone(zone)
            .toInstant()
            .toEpochMilli();

    System.out.println("Alarm will happen at millis " + triggerAlarmAtMillis);

输出为:

  

警报将发生在毫秒1543483560000

您可以使用在线纪元时间转换器来验证它是否符合格林尼治标准时间(GMT):2018年11月29日,星期四,09:26:00,与偏移量+05:30的14:56相同。链接在底部。

考虑避免使用Calendar和SimpleDateFormat

您使用的日期时间类存在严重的设计问题,被认为已过时。我建议您改用java.time。如果您的Android API级别需要,请通过ThreeTenABP,请参见下文。

我还建议您将日期和时间解析留给库方法。既不挑选单个字符也不提取子字符串,这是一种困难且容易出错的方法。

  

但是我想知道为什么上述方法是错误的?

Java的一个丑陋且令人惊讶的事实是,intchar在许多地方可以互换使用(已从C ++及其先驱者那里接手)。例如:

    String MM = c[3]+c[4]+"";

c[3]c[4]均为1,并且您曾希望此字符串为字符串"11"。没错该表达式从左到右求值,因此添加了int个等价字符。 1表示为数字49。49 + 49等于98。将98添加到空字符串时,它首先被转换为字符串本身(如预期的那样),因此得到字符串"98" 。同样,对于日期您将获得50 + 57 = 107,对于年份50 + 48 + 49 + 56 = 203。

下一个惊喜(我想)。虽然将Calendar的年份设置为203可能有意义,但将月份设置为98应该是错误的,并且会导致异常,对吗?不适用于具有默认设置的Calendar类。它只是对203年之后的年份进行计数,并在211年结束。类似,当您将月份中的日期设置为107时,它将对接下来的月份进行计数,并在211年6月15日星期六结束-仍然超过1800年以前。

但是您的代码中还有一个错误。在这里:

    cal.set(Calendar.MONTH, Integer.parseInt(MM));

即使MM已达到预期的11,也不会将月份设置为11月。关于Calendar的另一个令人困惑的事情是,月份数字是从0开始的:0是1月,依此类推,所以11是12月,而不是11月。

问题:我可以在Android上使用java.time吗?

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

  • 在Java 8和更高版本以及新的Android设备上(有人告诉我API级别为26),新的API是内置的。
  • 在Java 6和7中,获得了ThreeTen反向端口,即新类的反向端口(JSR 310的ThreeTen,首次描述了现代API)。
  • 在(较旧的)Android上,使用ThreeTen Backport的Android版本。叫做ThreeTenABP。确保从包org.threeten.bp和子包中导入日期和时间类。

链接