Почему это преобразование единицы времени возвращает нули? - PullRequest
1 голос
/ 19 января 2012

У меня проблема с кодом ниже.Он преобразует миллисекунды в месяцы, дни, часы и минуты.

long diffms = date2l - date1l; //The result here is in milliseconds; The value of date2l - date1l are different
long diff_minute = diffms / 60000;

long diff_hour = diff_minute / 60; float diff_minute_now = (diff_minute % 1) * 60; int dmn = (int) diff_minute_now;
long diff_day = diff_hour / 24; float diff_hour_now = (diff_hour % 1) * 24; int dhn = (int) diff_hour_now;
long diff_month = diff_day / 30; float diff_day_now = (diff_day % 1) * 30;  int ddn = (int) diff_day_now;   

diffe = new LabelField
("Remaining Time : " + Long.toString(diff_month) + " month(s) " 
                    + Integer.toString(ddn) + " day(s) " 
                    + Integer.toString(dhn) + " hour(s) "
                    + Integer.toString(dmn) + " minute(s)");
add(diffe);

Почему значения результата имеют все нули?

РЕДАКТИРОВАТЬ: @BicycleDude Я изменяю ваш код на:

long diffms = date2l - date1l;
long ts = diffms / 1000;

long mo = ts / 60 / 60 / 24 / 30;
long d = (ts - mo * 30 * 24 * 60 * 60) / (60 * 60 * 24);
long h = (ts - d * 24 * 60 * 60) / (60 * 60);
long m = (ts - h * 60 * 60) / 60;

Но часы не работают

Ответы [ 3 ]

5 голосов
/ 19 января 2012

'any% 1' вернет 0. Вероятно, это не то, что вы хотели.

  1. Переменные, которые вы делите изначально, имеют тип long.Так что их результаты тоже будут долгими.(например, 12345/100 = 123, а не 123.45).
  2. Оператор по модулю работает с остатком при делении целых чисел.(например, 12345% 100 = 45).
  3. Алгоритм, который вы указали, не извлекает день, месяц, час, минуту, секунду так, как вы ожидали.Требуется переделка, прежде чем она станет правильной.

Я переработал формулы, предполагая, что в месяце 31 день:

long diffms = date2l - date1l;
long mo = (diffms / 1000 / 60 / 60 / 24 / 31);
long d = (diffms / 1000 / 60 / 60 / 24) % 31;
long h = (diffms / 1000 / 60 / 60) % 24;
long m = (diffms / 1000 / 60) % 60;
long s = (diffms / 1000) % 60;
1 голос
/ 27 ноября 2012

Класс TimeUnit предоставляет фабричные методы, которые упрощают большую часть вашей работы:

import static java.util.concurrent.TimeUnit.*; 


// First, calculate the total difference in each unit
long diffDays = MILLISECONDS.toDays(diffMs);
long diffHours = MILLISECONDS.toHours(diffMs);
long diffMinutes = MILLISECONDS.toMinutes(diffMs);
long diffSeconds = MILLISECONDS.toSeconds(diffMs);

// Next, calculate the differences
long months = diffDays / 30;
long days = diffDays - 30 * months;
long hours = diffHours - DAYS.toHours(diffDays);
long minutes = diffMinutes - HOURS.toMinutes(diffHours);
long seconds = diffSeconds - MINUTES.toSeconds(diffMinutes);
1 голос
/ 19 января 2012

Я собираюсь основывать свой ответ на отредактированной части кода, поскольку BicycleDude уже указал, что не так с операциями по модулю.

long diffms = date2l - date1l; //difference in ms
long ts = diffms / 1000; //total difference in seconds

long mo = ts / 60 / 60 / 24 / 30; //(1)
long d = (ts - mo * 30 * 24 * 60 * 60) / (60 * 60 * 24); //follows on because of (1)
long h = (ts - d * 24 * 60 * 60) / (60 * 60); //follows on because of (1)
long m = (ts - h * 60 * 60) / 60; //follows on because of (1)

Хорошо, я думал, что будет несколько проблем, но я думаю ( думаю , я, вероятно, что-то упускаю ...), что основная ошибка исходит из вашего расчета месяцев, который я обозначил в коде по комментарию (1). Вы не можете рассчитать разницу в таких месяцах.

Почему? А что, если различий было больше одного месяца? Не нужно ли вместо этого делить на 31? Или если это был високосный год? Вы должны были бы разделить на 29, если бы это был февраль. Поскольку целочисленное деление не округляется или не учитывает десятичные дроби, вы можете получить неточности в своих расчетах разницы в месяцах. Вероятно, будет лучше, если вместо этого вы будете использовать разницу в часах для расчета разницы в днях, и оттуда вы сможете вычислить разницу в месяцах. ( Редактировать : я думаю, что вам также необходимо учитывать факторы, которые я упоминал выше, при расчете разницы в месяцах от разницы в днях, проверяя, каковы ваши "исходные" и "целевые" даты хотя я не был бы слишком уверен в том, чтобы написать это сам на этой стадии ...)

Поскольку у вас есть проблема с тем, как вы вычисляете разницу в месяцах, и вы используете ошибочное значение для вычисления разницы в днях, я думаю, что это приводит к ошибке, распространяющейся до некоторых других ваших значений (например, разница в часах).

EDIT

Ладно, я немного больше разбираюсь с кодом. Как я уже отмечал ранее, ваши расчеты по месяцам были опасны и влияли на ваши расчеты дней, что впоследствии могло привести к ошибкам.

С примером, приведенным вами в комментариях, ваш код имел несоответствие 3 дням в количестве дней. (Пример был с 19 января 2012 года по 3 мая 2012 года). Я запустил это против кода BicycleDude, и это было нормально.

Я опубликую код, и я только что добавил одну строку, чтобы узнать количество дней, исходя из того, сколько часов прошло.

long h = ts / 60 / 60; // hour part
long m = (ts - h * 60 * 60) / 60; // minute part
long s = (ts - h * 60 * 60 - m * 60); // second part
long d = h / 24;

Если вы хотите сделать так, чтобы вы могли читать, что «между * date_l и date1l 'есть w дней, x часов, y минут и z секунд", вы можете сделать что-то вроде этого:

long date2l = Timestamp.valueOf("2012-05-03 05:30:10").getTime();
long date1l = Timestamp.valueOf("2012-01-19 00:00:00").getTime();
long diffms = date2l - date1l; //difference in ms
long diff_seconds = diffms / 1000; //total difference in seconds
long diff_mins = diff_seconds / 60; //total difference in minutes
long diff_hours = diff_mins / 60; //total difference in hours
long diff_days = diff_hours / 24; //total difference in days

long x = (diff_seconds - diff_days * 60 * 60 * 24) / (60 * 60);
long y = ((diff_seconds - (diff_hours * 60 * 60))) / 60;
long z = ((diff_seconds - (diff_mins * 60)));
long w = diff_days;

System.out.println(w + " " + x + " " + y + " " + z);

И, похоже, работает.

Я не разобрался в части месяцев, потому что это гораздо более нетривиально, но да. Это вроде работает?

...