繁体   English   中英

如何创建一个单个表达式来显示两个日期之间的时差,如年,月,日,小时,分钟,秒

[英]How to create a single expression displaying time difference between two Date's as years, months, days, hours, minutes, seconds

如何创建单个 jasper报告JRExpression ,以yy年月日dd天,hh小时,mm分钟,ss的格式可视化两个java.util.Date之间的差异秒

java.util.Date startDate
java.util.Date endDate

JRExpression是单行,其中不允许声明变量,但是您可以使用条件语句(使用语法boolean ? yes:no boolean ? yes:no ,对于不熟悉的人,请想象一行System.out.println();

所需输出的示例(如果您有一个不错的解决方案,请删除不存在的单位描述,并考虑单数/复数,但是如果它是一系列if语句,则不必这样做):

2年8个月12天2小时53分钟10 s

1小时1分钟

2月2日至3月4日和3月4日至4月6日均为“ 1个月2天”,但是可以忽略夏令时-谢谢@Affe

其他要求:

  • 只能使用jasper报告依赖项 (不包括joda)。
  • 推荐的dk等于或小于1.7(如果仅是解决方案,则接受1.8)

无需将答案格式化为jasper报告表达式,它可以是一个简单的System.out.println代码(我很乐意稍后编辑您的答案以添加jasper报告表达式代码)。

((endDate.getTime()-startDate.getTime()) / (60 * 60 * 1000)) % 24 + " hour(s), " +  
((endDate.getTime()-startDate.getTime()) / (60 * 1000)) % 60 + " minute(s)"

我尝试了什么:

我在SO的碧玉报告部分回答了多个问题,这个问题在报告生成中很常见。 我希望我可以链接一个java部分中的一个好答案,而不是在这个问题上传递代码(我只知道部分解决此问题)

这是在有关问题的示例: 计算时间和日期差

一些参考代码:

用Java计算日期/时间差

如何在Java中找到两个日期之间的差值的持续时间?

对于您熟悉的jasper report,我不想使用变量声明,因为如果用户需要在参数上使用它,这会使解决方案无效。

Calendar API无法直接用于此问题:每个操作都需要多行,因为有趣的方法将返回void并且无法链接。

这是一个很大的范围,但是,正如JasperReports的依赖项中所列出的那样,存在org.codehaus.castor:castor-xml:1.3.3 ,它自身取决于commons-lang:commons-lang:2.6 因此,我们可以使用commons-lang存在的DurationFormatUtils.formatPeriod(startMillis, endMillis, format)方法。 这里使用的字符串格式为

"y' years 'M' months 'd' days 'H' hours 'm' minutes 's' seconds'"

这将打印所需的字符串。 仍必须小心:这将包括0(例如"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>

输出为:

在此处输入图片说明


如果以上内容看起来太脆弱(因为不可能对所有JasperReports版本都存在对commons-lang的显式依赖), 那么还有另一种可能的解决方案,使用Java 8中引入的Java Time API

太可怕了 (我不认为有一种更简单的方法),但是输出与上面的完全相同,其中startend都是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")
);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM