2

I am creating a 'choice' inside a contract template that requires checking today's date. My DAML code is as follows:

controller dealer can
      Add_Car : CarId
        with
            startCoverage: Date

        do
          -- Check for a legal start date
          assert (
            startCoverage > *today* --should check that its not before today
            )
          create this with date_vehicle_added = startCoverage

What is the name of the function I can use to get the current date? It needs to go where it says "*today*".

4

2 回答 2

3

tldr:使用getTime : Update Timeand toDateUTC : Time -> Date,但要注意陷阱。如果可能,最好使用公证日期模式。

隐式建模日期/时间

建模日期和时间始终是一个微妙的问题,在处理诸如数字分类帐之类的确定性分布式系统时更是如此。DAML 提供了一个原始函数getTime,该函数将返回“账本有效时间” LET(可以使用 中的toDateUTC函数 将其转换为 UTC 日期DA.Date。这是对您问题的直接回答,但有几点需要注意。

  1. 此时间和日期采用 UTC,您必须明确建模它与本地时间的对应关系。由于 DAML 是一个确定性的分布式系统,因此没有本地时间,因为任何给定的事务都必须跨多个时区确定性地执行。

  2. 无故使用日期/时间比较可能会导致合同由于时间的流逝而隐含地停止。如果一个选项受到挂钟时间检查的保护,这可能意味着您的应用程序处理练习的任何延迟都可能导致该选项无效。确保您在应用程序代码中正确处理这种情况是一个微妙的问题——由于这是您选择的隐含参数,因此即使您有提前警告,也无法避免该问题的操作干预。

  3. 在存在显式时间比较的情况下,模型和应用程序的集成测试变得不确定且不可重复。虽然您可以为您的模型编写可重复Scenario的测试,因为您可以明确控制LET那里,这不会锻炼您的账本外应用程序。

显式建模日期/时间

另一种选择是公证日期模式。在这里,合同的签署人同意受信任的一方来公证当前日期。这种公证采用账本CurrentDate合同的形式。该合同以公证人为签字人,通常有一个单一的消费选择,由公证人控制,以提前日期。

如果您使用这种方法,您的Add_Car选择将采用一个额外的参数currentDate : ContractId CurrentDate,您可以将其视为提供证据的控制人,或证明商定的公证人已就本合同的目的证明了当前日期。这解决了隐式时间模型的问题,因此:

  1. 由于 Date 现在在账本上是明确的,因此在CurrentDate合同的进程中时区变得明确。

  2. 虽然如果公证人推进当前日期合同,合同仍可能被搁置,但日期管理的明确性质意味着 a) 在公证人日期更新之前排序的任何行使都将成功处理;这意味着,b) 现在有一种操作干预的途径,您可以提前警告给定日期的处理已落后于计划 - 假设公证人协议预期并允许此类干预。

  3. 因为您的系统的操作再次是账本内容的纯函数,所以更大的应用程序的行为变得确定性和可重复性。这大大减少了维护、测试和调试所需的工作量。

出于这些原因,我建议在可能的情况下使用公证日期模式,为确实没有替代方案的情况保留隐式日期处理。

于 2019-02-20T01:16:53.487 回答
2

在你之前assert,你可以绑定getTime函数的结果。然后我建议通过DA.Date中的and函数转换startCoverage为 a 。TimetoGregoriandatetime

您可能没有足够的信息来正确使用示例代码执行此操作;Date是一个“本地日期”,预计将相对于某个时区进行解释,而Time是一个绝对的 UNIX 纪元偏移量。正是出于这个原因,toDateUTC手册中列出了很多警告,我建议避免使用该功能。

此外,请记住,只有“账本有效时间”可用,这与“当前时间”并不完全相同。当然,为了实时练习Add_Car,getTime的结果将对应于当前时间。然而,交易必然是可重放的(出于验证或其他原因),并且对于那些执行getTime将产生它最初在行使时所做的事情。您无法使用getTimeDAML 来确定执行某些代码所花费的挂钟时间量,这意味着即使在实时练习期间,分类帐的有效时间也不能与挂钟精确对应。运行测试场景时,时间从 UNIX 纪元开始,可以根据测试需要在您的场景中手动推进;事实上,我可以推荐使用passpassToDate测试您正在编写的合同。

于 2019-02-20T01:13:26.470 回答