Как создать одно выражение, отображающее разницу во времени между двумя датами в виде лет, месяцев, дней, часов, минут, секунд
Как я могу создать одиночный отчет Джаспера JRExpression , который визуализирует разницу между двумя java.util.Date в формате yy year(s) month (s) DD day (s), hh hour(s), mm minute( s), ss second (s)
java.util.Date startDate
java.util.Date endDate
JRExpression-это одна строка, в которой объявление переменной не допускается, однако вы можете использовать условные операторы с использованием синтаксиса boolean ? yes:no, для вас, кто не знаком, представьте себе одну строку System.out.println();
Пример желаемого вывода (Если у вас есть хорошее решение удалить описание единицы, когда ее нет, и рассмотрим единственное / множественное число, но это не обязательно, если это серия утверждений if):
2 года, 8 месяцев, 12 дней, 2 часа, 53 минуты, 10 с
1 час, 1 минута
И 2 февраля - 4 марта, и 4 марта-6 апреля-это "1 месяц, 2 дня", переход на летнее время, однако, можно игнорировать-спасибо @Affe
Дополнительные требования:
- можно использовать только отчет Джаспера зависимости (joda не является включенный).
- предпочтительный jdk 1.7 или меньше (1.8 принимается, если это только решение)
Нет необходимости форматировать ответ как выражение отчета Джаспера это может быть простой код System.out.println (я с удовольствием отредактирую ваш ответ позже, чтобы также добавить код выражения отчета Джаспера). Пример
((endDate.getTime()-startDate.getTime()) / (60 * 60 * 1000)) % 24 + " hour(s), " +
((endDate.getTime()-startDate.getTime()) / (60 * 1000)) % 60 + " minute(s)"
Что я пробовал:
я отвечаю на несколько вопросов в разделе отчета jasper SO, и этот вопрос часто используется при создании отчетов. Я бы предпочел хороший ответ из раздела java, который я могу связать, а не передавать свой код по этому вопросу (который я знал бы только частично решить в качестве примера)
Это пример по вопросу в jasper-report: вычисление разницы во времени и дате
Некоторый справочный код:
Вычислить разницу дат / времени в java
Как найти длительность разницы между двумя датами на Яве?
для вас это так я не хочу использовать объявление переменной, так как это приведет к недействительности решения, если пользователю потребуется использовать его для параметров.
1 ответ:
API календаря не может быть непосредственно использован для этой проблемы: каждая операция потребует нескольких строк, так как интересные методы возвращают
voidи не могут быть связаны.Это очень большая натяжка, но, как указано в зависимостях JasperReports , существует
org.codehaus.castor:castor-xml:1.3.3которая сама зависит отcommons-lang:commons-lang:2.6. Поэтому мы можем использоватьDurationFormatUtils.formatPeriod(startMillis, endMillis, format)метод, который присутствует вcommons-lang. Строка формата для использования здесь будет быть"y' years 'M' months 'd' days 'H' hours 'm' minutes 's' seconds'"Который напечатает нужную строку. Все еще необходимо соблюдать осторожность: это будет включать 0s (например,
"0 months") и также будет иметь неправильную множественность (например,"1 months").
- мы можем использовать регулярное выражение
"(?<!\\d)0 (\\w+) ?", чтобы удалить все 0 для строки. Это регулярное выражение соответствует любому 0, , которому не предшествует цифра (мы не хотим, например, соответствовать 10), за которым следует один или несколько символов слова и, возможно, следует пробел.- тогда мы можем использовать регулярные выражение
"(?<!\\d)1 (\\w+)s", чтобы соответствовать каждому появлению"1 ...s"и заменить его на"1 ...", чтобы иметь надлежащую множественность. Это регулярное выражение соответствует любому 1, не предваренному цифрой, за которым следует один или несколько символов слова (захваченных в группе), заканчивающихся наs; оно будет заменено на"1 $1", т. е. 1, за которым следует захваченное значение.Пример:
System.out.println( org.apache.commons.lang.time.DurationFormatUtils.formatPeriod( startDate.getTime(), endDate.getTime(), "y' years 'M' months 'd' days 'H' hours 'm' minutes 's' seconds'" ) .replaceAll("(?<!\\d)0 (\\w+) ?", "") .replaceAll("(?<!\\d)1 (\\w+)s", "1 $1") );Все это можно сделать с Java 7 или ниже.
В JasperReports это было бы пример:
<?xml version="1.0" encoding="UTF-8"?> <!-- Created with Jaspersoft Studio version 6.2.1.final using JasperReports Library version 6.2.1 --> <jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports jasperreports.sourceforge.net/…" name="Blank_A4" pageWidth="595" pageHeight="842" whenNoDataType="AllSectionsNoDetail" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="f067f2c4-395f-4669-9fda-4fe81cc59227"> <property name="com.jaspersoft.studio.data.defaultdataadapter" value="One Empty Record"/> <parameter name="dateStart" class="java.util.Date" isForPrompting="false"> <defaultValueExpression><![CDATA[new java.util.Date(1)]]></defaultValueExpression> </parameter> <parameter name="dateEnd" class="java.util.Date" isForPrompting="false"> <defaultValueExpression><![CDATA[new java.util.Date()]]></defaultValueExpression> </parameter> <queryString><![CDATA[]]></queryString> <title> <band height="43" splitType="Stretch"> <textField> <reportElement x="0" y="0" width="560" height="30" uuid="cc03531c-2983-4f9a-9619-2826ed92760e"/> <textFieldExpression><![CDATA[org.apache.commons.lang.time.DurationFormatUtils.formatPeriod($P{dateStart}.getTime(),$P{dateEnd}.getTime(),"y' years 'M' months 'd' days 'H' hours 'm' minutes 's' seconds'").replaceAll("(?<!\\d)0 (\\w+) ?", "").replaceAll("(?<!\\d)1 (\\w+)s", "1 $1")]]></textFieldExpression> </textField> </band> </title> </jasperReport>С выходом:
Если вышесказанное выглядит слишком хрупким (из-за явной зависимости к
commons-lang, которая не может быть там для всех версий JasperReports), есть другое возможное решение с использованием JAVA Time API, введенного в Java 8.Это ужасно (я не думаю, что есть более простой способ), но выход точно такой же, как и выше, где
startиendесть и то и другоеLocalDateTimeобъекты:System.out.println(( ChronoUnit.YEARS.between(start, end) + " years " + ChronoUnit.MONTHS.between(start.plusYears(ChronoUnit.YEARS.between(start, end)), end) + " months " + ChronoUnit.DAYS.between(start.plusYears(ChronoUnit.YEARS.between(start, end)).plusMonths(ChronoUnit.MONTHS.between(start.plusYears(ChronoUnit.YEARS.between(start, end)), end)), end) + " days " + ChronoUnit.HOURS.between(start.plusYears(ChronoUnit.YEARS.between(start, end)).plusMonths(ChronoUnit.MONTHS.between(start.plusYears(ChronoUnit.YEARS.between(start, end)), end)).plusDays(ChronoUnit.DAYS.between(start.plusYears(ChronoUnit.YEARS.between(start, end)).plusMonths(ChronoUnit.MONTHS.between(start.plusYears(ChronoUnit.YEARS.between(start, end)), end)), end)), end) + " hours " + ChronoUnit.MINUTES.between(start.plusYears(ChronoUnit.YEARS.between(start, end)).plusMonths(ChronoUnit.MONTHS.between(start.plusYears(ChronoUnit.YEARS.between(start, end)), end)).plusDays(ChronoUnit.DAYS.between(start.plusYears(ChronoUnit.YEARS.between(start, end)).plusMonths(ChronoUnit.MONTHS.between(start.plusYears(ChronoUnit.YEARS.between(start, end)), end)), end)).plusHours(ChronoUnit.HOURS.between(start.plusYears(ChronoUnit.YEARS.between(start, end)).plusMonths(ChronoUnit.MONTHS.between(start.plusYears(ChronoUnit.YEARS.between(start, end)), end)).plusDays(ChronoUnit.DAYS.between(start.plusYears(ChronoUnit.YEARS.between(start, end)).plusMonths(ChronoUnit.MONTHS.between(start.plusYears(ChronoUnit.YEARS.between(start, end)), end)), end)), end)), end) + " minutes " + ChronoUnit.SECONDS.between(start.plusYears(ChronoUnit.YEARS.between(start, end)).plusMonths(ChronoUnit.MONTHS.between(start.plusYears(ChronoUnit.YEARS.between(start, end)), end)).plusDays(ChronoUnit.DAYS.between(start.plusYears(ChronoUnit.YEARS.between(start, end)).plusMonths(ChronoUnit.MONTHS.between(start.plusYears(ChronoUnit.YEARS.between(start, end)), end)), end)).plusHours(ChronoUnit.HOURS.between(start.plusYears(ChronoUnit.YEARS.between(start, end)).plusMonths(ChronoUnit.MONTHS.between(start.plusYears(ChronoUnit.YEARS.between(start, end)), end)).plusDays(ChronoUnit.DAYS.between(start.plusYears(ChronoUnit.YEARS.between(start, end)).plusMonths(ChronoUnit.MONTHS.between(start.plusYears(ChronoUnit.YEARS.between(start, end)), end)), end)), end)).plusMinutes(ChronoUnit.MINUTES.between(start.plusYears(ChronoUnit.YEARS.between(start, end)).plusMonths(ChronoUnit.MONTHS.between(start.plusYears(ChronoUnit.YEARS.between(start, end)), end)).plusDays(ChronoUnit.DAYS.between(start.plusYears(ChronoUnit.YEARS.between(start, end)).plusMonths(ChronoUnit.MONTHS.between(start.plusYears(ChronoUnit.YEARS.between(start, end)), end)), end)).plusHours(ChronoUnit.HOURS.between(start.plusYears(ChronoUnit.YEARS.between(start, end)).plusMonths(ChronoUnit.MONTHS.between(start.plusYears(ChronoUnit.YEARS.between(start, end)), end)).plusDays(ChronoUnit.DAYS.between(start.plusYears(ChronoUnit.YEARS.between(start, end)).plusMonths(ChronoUnit.MONTHS.between(start.plusYears(ChronoUnit.YEARS.between(start, end)), end)), end)), end)), end)), end) + " seconds" ) .replaceAll("(?<!\\d)0 (\\w+) ?", "") .replaceAll("(?<!\\d)1 (\\w+)s", "1 $1") );
