草庐IT

java - 使用 p :calendar (no validation) 相互限制开始和结束日期时间

coder 2023-05-14 原文

我们需要向用户呈现两个 p:calendar 组件,分别代表一个开始日期和结束日期。两个日期时间都有日期、小时和分钟。 PrimeFaces 有完美的 mindatemaxdateminHourmaxHourminMinuteminMinute 属性可用。

现在的要求是:

不可能将开始日期时间设置为大于或等于结束日期时间的任何值。 无法将结束日期时间设置为小于或等于结束日期时间的任何值。

以下等式应该成立:

begin datetime < end datetime

现在我们尝试了以下 JSF:

<p:calendar id="begin-date"
            value="#{debugManager.selectedBeginDate}"
            mindate="#{debugManager.minBeginDate}"
            maxdate="#{debugManager.maxBeginDate}"
            maxHour="#{debugManager.maxBeginHour}"
            maxMinute="#{debugManager.maxBeginMinute}"
            pattern="yyyy-MM-dd HH:mm"
            showButtonPanel="true"
            readonlyInput="true"
            navigator="true"
            showOn="button"
            required="true">
    <p:ajax event="dateSelect" update="end-date" />
</p:calendar>

<p:calendar id="end-date"
            value="#{debugManager.selectedEndDate}"
            mindate="#{debugManager.minEndDate}"
            minHour="#{debugManager.minEndHour}"
            minMinute="#{debugManager.minEndMinute}"
            pattern="yyyy-MM-dd HH:mm"
            showButtonPanel="true"
            readonlyInput="true"
            navigator="true"
            showOn="button">
    <p:ajax event="dateSelect" update="begin-date" />
</p:calendar>

这是一个示例性的最小/最大方法(结束日期的分钟):

public Date getMinEndDate()
{
    return this.getSelectedBeginDate();
}

如您所见,最短结束日期是当前 AJAX 选择的开始日期。正确设置结束日期不允许将开始日期设置为超过结束日期。

等式中涉及时间时,问题就开始了……

由于 p:calendar 的接口(interface)有单独的方法,所以 bean 必须提供逻辑:

public int getMinEndHour()
{
    Date selectedBeginDate = this.getSelectedBeginDate();
    Date selectedEndDate = this.getSelectedEndDate();

    if ( selectedBeginDate != null && DateUtil.isSameDay( selectedBeginDate, selectedEndDate ) )
    {
        return DateUtil.getHourOf( selectedBeginDate );
    }

    return ComplianceConstants.DEFAULT_COMPLIANCE_CASE_MIN_END_HOUR;
}

这基本上只表示如果设置了开始日期并且开始日期和结束日期当前相同,则将可选择的结束时间(结束日期的minHour)限制为开始时间。

操作:

Set the begin datetime to 2013-04-20 12:34 (legit)
Set the end   datetime to 2013-04-22 00:00 (legit)

现在结束日期的时间是 00:00,只要将结束时间调整为至少 12:35,就应该允许选择日历日期 2013-04-20。

p:calendar 组件现在无法知道这一点

sets the end datetime to 2013-04-20 00:00 (legit, but false)

...

现在的问题是,当用户在日历中按下某个新的结束日期时,mindate/maxdate 属性无法限制用户点击与开始日期相同的日期。如果结束日期时间现在恰好早于相同开始日期的时间,我们将无能为力(这是错误的)。

现在的后续问题是用户能够关闭日历并只需按下提交按钮即可将虚假数据插入数据库。当然,可以/应该运行 validator ,但是我们必须在没有 validator 的情况下以某种方式实现这一点

我们接下来尝试的是修补 setSelectedBeginDate( Date selectedBeginDate )setSelectedEndDate( Date selectedEndDate ) 方法来调整设置 java.util.Date 时间部分,如果日期在同一天。像这样的:

public void adjustSelectedEndDate()
{
    if ( this.selectedEndDate != null )
    {
        this.log.infov( "adjustSelectedEndDate: b-hour = {0}, e-hour = {1}", DateUtil.getHourOf( this.selectedBeginDate ), DateUtil.getHourOf( this.selectedEndDate ) );

        if ( DateUtil.isSameDay( this.selectedBeginDate, this.selectedEndDate ) &&
            ( DateUtil.getHourOf( this.selectedEndDate ) < DateUtil.getHourOf( this.selectedBeginDate ) ) ||
              DateUtil.getHourOf( this.selectedEndDate ) == DateUtil.getHourOf( this.selectedBeginDate ) && DateUtil.getMinuteOf( this.selectedEndDate ) <= DateUtil.getMinuteOf( this.selectedBeginDate ) )
        {
            this.log.info( "Adjusting selected end date!" );

            this.selectedEndDate = DateUtil.addOneMinuteTo( DateUtil.copyTime( this.selectedBeginDate, this.selectedEndDate ) );
        }
    }
}

这要求我们将 @this 添加到每个 p:calendarupdate 属性中,以便相应的 getter (getSelectedBeginDate ()getSelectedEndDate + 最小/最大限制器)将在更新期间调用。

在更新上放置 @this 但是会混淆 p:calendar 组件,使时间 slider 只能滑动一次。随后的 slider 事件将被简单地忽略,表现不佳。

问题

  • 您通常如何解决这个问题?
  • 是使用 p:remoteCommand 的方式来实现我们想要的吗?

可选问:

  • 为什么没有实现 PrimeFaces p:calendar 以提供单个 minDateTime 和 maxDateTime,这可能会解决手头的问题?

我敢打赌,我描述的这种情况之前已经解决了。如果您能描述您设法解决此问题的方法(或什至分享部分解决方案),我将不胜感激。

最佳答案

前言:

我不与 JSF 合作,但有几件事可能会引导你回到你想去的地方:

a) 当 working with just the date portion of a dateTime in a standard calendar ,考虑使用:

someCalendar.set(Calendar.MILLISECOND, 0)

b) 考虑使用 joda-time ,因为它似乎经常被推荐( hereheremany other places )而不是标准库,以确保在许多情况下的正确性、性能和易用性。

c) 确保您的 bean 范围在每个 ajax 调用(不重定向,仅发送标准回发等)中幸存下来,并且每个事件处理程序都在获取 faces 上下文(例如。FacesContext facesContext = FacesContext.getCurrentInstance();)

d) mindate之类的东西可能不会像你期望的那样工作,而且我不认为自动行为会如此容易插入。

当这些选项不可用时,您必须自己动手:

哲学/用户体验: 我要做的第一件事是从这对日期中消除对安排或视角的期望。不要将该对视为在时间轴上暴露或期望方向的 vector 。

  • 换句话说,是一个startfrom日期总是小于或早于 endto日期?不,正如查询历史数据或对尚未发生或已经发生的事件应用更正所看到的那样?

    这种含义很容易让用户混淆他们是“返回”还是“前进”(并且很容易混淆您自己)。相反,我会将它们之间有一个时间段的一对日期视为公正而简单的 a pair of datesrangeperiod声明一个间隔,并根据任何随后选择的值推断它们在时间线上的相对位置。通过这种方式,您可以尊重日期从不相等的各自和固有的要求,左边总是在左边,右边总是在右边。

我们无法推断“开始”或“从”是什么意思,但我们可以推断出一些含义和相对关系:在时间轴上的右、左和中间。 注意:在进行任何计算或比较之前,请始终将日期解析为 UTC。

long oneDateValue = oneDate.toUtc().toMilliseconds();
long anotherDateValue = anotherDate.toUtc().toMilliseconds();

long right = max (oneDateValue, anotherDateValue);
long left = min (oneDateValue, anotherDateValue);

评估精度: 在使用任何语言处理一系列日期时,我会考虑的第二件事类似于处理 float 的方式。对于比较,不要比较是否相等,而是将增量与“可接受的错误级别”进行比较。换句话说,应用程序实际上只关心一定程度的精度,因此请确保仅捕获和考虑该精度:

const int dateTimeResolutionInMs = 86400000; // milliseconds per day

public bool areEssentiallySame(long left, long right) {

   // the difference between right and left is less than our precision 
   // requires, thus dates are effectively the same
   return (right - left < dateTimeResolutionInMs);
}

强制精度: 第三,即使在分辨率范围内,我们如何解决值的差异? (Out 应用程序的精度超出了它可以处理、预期或需要的程度)。

long diff = value % dateTimeResolutionInMs;

  1. 截断:return value - diff;

  2. 最近的(有偏差):return value + (diff < dateTimeResolutionInMs/ 2) ? -1 * diff : dateTimeResolutionInMs - diff;

  3. 其他:还有许多其他策略可以将值缩小或扩大到首选分辨率或精度

附录: 至于获取回发/Ajax 调用以返回一个 View ,该 View 具有您对 calendar 触发的事件所期望的值。元素,如果前言中的注释没有让你得到任何地方,你可能想把这个问题分离到一个新问题上,而你 know for certain your bean is properly registered and recognized.您可能会遇到一些特定于浏览器/浏览器版本的问题,这些问题会导致不良行为,并且与其他任何事情一样,存在已知和未知的问题。

关于java - 使用 p :calendar (no validation) 相互限制开始和结束日期时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16162554/

有关java - 使用 p :calendar (no validation) 相互限制开始和结束日期时间的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  5. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  6. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  7. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  8. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  9. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  10. ruby - 在 64 位 Snow Leopard 上使用 rvm、postgres 9.0、ruby 1.9.2-p136 安装 pg gem 时出现问题 - 2

    我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po

随机推荐