1

We have recently upgraded our site to plone 4 and noticed our calender picker doesnt work if date is older then 1970. After small debugging, noticed this line is issue

plone.app.form.widgets.datecomponents.py -> result method

for date less then 1970 date.timeTime result negative value and localtime method expecting positive value I assume.

local_zone = date.localZone(localtime(date.timeTime()))

Any help, idea or suggestion is always good

Here is traceback

Traceback (innermost last):
  Module ZPublisher.Publish, line 126, in publish
  Module ZPublisher.mapply, line 77, in mapply
  Module ZPublisher.Publish, line 46, in call_object
  Module Products.CMFFormController.ControllerPageTemplate, line 75, in __call__
  Module Products.CMFFormController.BaseControllerPageTemplate, line 31, in _call
  Module Shared.DC.Scripts.Bindings, line 322, in __call__
  Module Shared.DC.Scripts.Bindings, line 359, in _bindAndExec
  Module Products.PageTemplates.ZopePageTemplate, line 334, in _exec
  Module Products.PageTemplates.ZopePageTemplate, line 431, in pt_render
  Module Products.PageTemplates.PageTemplate, line 79, in pt_render
  Module zope.pagetemplate.pagetemplate, line 113, in pt_render
  Module zope.tal.talinterpreter, line 271, in __call__
  Module zope.tal.talinterpreter, line 343, in interpret
  Module zope.tal.talinterpreter, line 888, in do_useMacro
  Module zope.tal.talinterpreter, line 343, in interpret
  Module zope.tal.talinterpreter, line 533, in do_optTag_tal
  Module zope.tal.talinterpreter, line 518, in do_optTag
  Module zope.tal.talinterpreter, line 513, in no_tag
  Module zope.tal.talinterpreter, line 343, in interpret
  Module zope.tal.talinterpreter, line 954, in do_defineSlot
  Module zope.tal.talinterpreter, line 343, in interpret
  Module zope.tal.talinterpreter, line 533, in do_optTag_tal
  Module zope.tal.talinterpreter, line 518, in do_optTag
  Module zope.tal.talinterpreter, line 513, in no_tag
  Module zope.tal.talinterpreter, line 343, in interpret
  Module zope.tal.talinterpreter, line 858, in do_defineMacro
  Module zope.tal.talinterpreter, line 343, in interpret
  Module zope.tal.talinterpreter, line 954, in do_defineSlot
  Module zope.tal.talinterpreter, line 343, in interpret
  Module zope.tal.talinterpreter, line 533, in do_optTag_tal
  Module zope.tal.talinterpreter, line 518, in do_optTag
  Module zope.tal.talinterpreter, line 513, in no_tag
  Module zope.tal.talinterpreter, line 343, in interpret
  Module zope.tal.talinterpreter, line 946, in do_defineSlot
  Module zope.tal.talinterpreter, line 343, in interpret
  Module zope.tal.talinterpreter, line 533, in do_optTag_tal
  Module zope.tal.talinterpreter, line 518, in do_optTag
  Module zope.tal.talinterpreter, line 513, in no_tag
  Module zope.tal.talinterpreter, line 343, in interpret
  Module zope.tal.talinterpreter, line 821, in do_loop_tal
  Module zope.tal.talinterpreter, line 343, in interpret
  Module zope.tal.talinterpreter, line 533, in do_optTag_tal
  Module zope.tal.talinterpreter, line 518, in do_optTag
  Module zope.tal.talinterpreter, line 513, in no_tag
  Module zope.tal.talinterpreter, line 343, in interpret
  Module zope.tal.talinterpreter, line 888, in do_useMacro
  Module zope.tal.talinterpreter, line 343, in interpret
  Module zope.tal.talinterpreter, line 583, in do_setLocal_tal
  Module zope.tales.tales, line 696, in evaluate
   - URL: calendar_macros
   - Line 12, Column 4
   - Expression: <PythonExpr date_components_support_view.result(inputvalue, 0, starting_year, ending_year, future_years)>
   - Names:
      {'container': <ATFolder at /rcseng/account>,
       'context': <ATFolder at /rcseng/account>,
       'default': <object object at 0x01DE1830>,
       'here': <ATFolder at /rcseng/account>,
       'loop': {u'record': <Products.PageTemplates.Expressions.PathIterator object at 0x0E0BEAB0>},
       'nothing': None,
       'options': {'args': (),
                   'state': <Products.CMFFormController.ControllerState.ControllerState object at 0x0E287F30>},
       'repeat': <Products.PageTemplates.Expressions.SafeMapping object at 0x0E21E810>,
       'request': <HTTPRequest, URL=http://dev.rcseng.ac.uk/account/my_details>,
       'root': <Application at >,
       'template': <ControllerPageTemplate at /rcseng/account/my_details>,
       'traverse_subpath': [],
       'user': <PloneUser '227225'>}
  Module Products.PageTemplates.ZRPythonExpr, line 48, in __call__
   - __traceback_info__: date_components_support_view.result(inputvalue, 0, starting_year, ending_year, future_years)
  Module PythonExpr, line 1, in <expression>
  Module plone.app.form.widgets.datecomponents, line 97, in result
ValueError: (22, 'Invalid argument')
4

1 回答 1

3

进一步调查后,确实可以重现您报告的问题。在除Windows之外的大多数平台上,我都能很好地输入前纪元(1970 年 1 月 1 日)日期。

确实如此,Zope 的 DateTime 实例在纪元之前使用负秒值作为时间戳,但 Python通常time.localtime可以很好地处理负值:

>>> import time
>>> time.localtime(-10000)
time.struct_time(tm_year=1969, tm_mon=12, tm_mday=31, tm_hour=22, tm_min=13, tm_sec=20, tm_wday=2, tm_yday=365, tm_isdst=0)

我已经在 Mac、FreeBSD 和 Linux 上的几个 python 2.x 版本中对此进行了测试。但是,当您在 Windows 上进行测试时,您确实会收到 ValueError。请注意,这是一个跨 python 和 Plone 版本的问题,这是一个特定于 Windows 的问题!

有问题的代码试图确定给定日期的本地时区,这可能是夏令时(夏令时)或冬令时。因此,在 Windows 上,我们也可以将日期中的年份换成当前年份,这样计算才能起作用。它可能会导致 DST 计算错误,具体取决于确切的当地时区,但由于无论如何您都无法获得 1970 年前日期的正确计算,因此这是一个很好的折衷方案。

我刚刚将第 97 行的以下替换提交给了 git(commit 63b043a7ba):

try:
    local_zone = date.localZone(localtime(date.timeTime()))
except ValueError:
    # Dates before 1970 use a negative timeTime() value, which on
    # on some platforms are not handled well and lead to a ValueError.
    # In those cases, calculate the local timezone (which is DST based)
    # from the same date in the *current year* instead. This is better
    # than failing altogether!
    timeZoneDate = DateTime(localtime().tm_year, *date.parts()[1:])
    local_zone = date.localZone(localtime(timeZoneDate.timeTime()))

在你的本地 egg 中使用它,或者等待包的 2.1 分支的新版本。

于 2012-08-02T16:10:40.070 回答