Смущает метод класса () класса Calendar в Android - PullRequest
0 голосов
/ 29 ноября 2018
 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 для отправки намерения 28-11-2018 в 14: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.

Устанавливаю ли я время в прошлом и как его исправить?

РЕДАКТИРОВАТЬ: Я использовалтекст редактирования для отображения времени и 29-11-2018 становится 15-06-0211.How?

РЕДАКТИРОВАТЬ: Возможно, это не так.

 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 голосов
/ 29 ноября 2018

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

Вы можете использовать онлайн-конвертер времени эпохичтобы убедиться, что это соответствует времени по Гринвичу: четверг 29. ноября 2018 г. 09:26:00, что, в свою очередь, соответствует 14:56 по смещению +05: 30.Ссылка внизу.

Не используйте Calendar и SimpleDateFormat

Используемые вами классы даты и времени имеют серьезные проблемы с дизайном и считаются давно устаревшими.Я рекомендую вместо этого использовать java.time.Если необходимо для вашего уровня API Android, то через ThreeTenABP, см. Ниже.

Также я рекомендую оставить анализ даты и времени для методов библиотеки.Для этого не нужно выделять ни символы, ни подстроки, это сложный и подверженный ошибкам способ.

Но я хочу знать, почему вышеуказанный метод неправильный?

Это ужасный и удивительный факт Java, что во многих местах int и char могут использоваться взаимозаменяемо (это было перенято из 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, он продолжает считать дни в следующих месяцах и заканчивается в субботу 15 июня 211 года - все еще более 1800 летназад.

И все же есть еще одна ошибка в вашем коде.Здесь:

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

Даже если бы MM было 11, как предполагалось, это не установило бы месяц на ноябрь.Еще одна запутанная вещь в Calendar состоит в том, что номера месяцев основаны на 0: 0 - январь и т. Д., Поэтому 11 - декабрь, а не ноябрь.

Вопрос: Можно ли использовать java.time на Android?

Да, java.time прекрасно работает на старых и новых устройствах Android.Для этого требуется как минимум Java 6 .

  • В Java 8 и более поздних версиях и на новых устройствах Android (от уровня API 26, как мне сказали) новый API поставляется
  • В Java 6 и 7 получите ThreeTen Backport, бэкпорт новых классов (ThreeTen для JSR 310, где впервые был описан современный API).
  • На (более старом) Android, используйте Android-версию ThreeTen Backport.Это называется ThreeTenABP.Убедитесь, что вы импортируете классы даты и времени из пакета org.threeten.bp и подпакетов.

Ссылки

0 голосов
/ 29 ноября 2018

Вы извлекаете неправильные значения из 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);
...