IS_DATETIME validator a real mess

35 views
Skip to first unread message

Lucas

unread,
Nov 6, 2025, 11:13:13 PM (7 days ago) Nov 6
to py4web
hello one and all,

below is a simple test code with 3 fields where the input field is really the test of the IS_DATETIME validator is tested.  the default is commented out because I couldn't get it to compile and IS_DATETIME doesn't show the seconds as required in the format and instead PM/AM shows up even though %H should be in 24-hour format.  so what is the format option to exclude the AM/PM altogether that lets the 24-hour format work it out.

and when you hit submit, all kinds of hellfire and damnation comes out of the exception but mainly focusing on "ValueError: time data '' does not match format '%Y-%m-%d %H:%M:%S'"".

so there you have it.  Lucas



@action("datetime_test")
@action.uses("index.html", db, auth, session, T)
def datetime_test():
    fields = [
    Field("name", length=12, requires=IS_NOT_EMPTY(), default='name',),
    Field('input', 'datetime', requires=IS_DATETIME(format=T('%Y-%m-%d %H:%M:%S'), error_message='must be YYYY-MM-DD HH:MM:SS!'),),# default=datetime.now(),),
    Field('duration', 'integer', requires=IS_INT_IN_RANGE(1,1e6), default=200,),
    ]
    frm = Form(fields)
    return dict(message=frm)

Massimo DiPierro

unread,
Nov 9, 2025, 9:42:22 AM (4 days ago) Nov 9
to py4web
There are two problems

1) You have an extra , after now() and that makes default a tuple not a datetime
2) format should be a string so format=str(T(...)) works. 

this works:

fields = [
Field("name", length=12, requires=IS_NOT_EMPTY(), default='name',),
Field('input', 'datetime', requires=IS_DATETIME(format=T('%Y-%m-%d %H:%M:%S'), error_message='must be YYYY-MM-DD HH:MM:SS!'), default=datetime.datetime.now()),
Field('duration', 'integer', requires=IS_INT_IN_RANGE(1,1e6), default=200,),
]
frm = Form(fields)

I think we should not need the str(...) and it should be automatic. I will fix that.

Massimo DiPierro

unread,
Nov 9, 2025, 9:53:52 AM (4 days ago) Nov 9
to py4web
The str(T(....)) is fixed in version 1.20251109.1 and now you can simply do T(...) as in your example

On Thursday, 6 November 2025 at 20:13:13 UTC-8 Lucas wrote:

Lucas

unread,
Nov 9, 2025, 4:33:25 PM (4 days ago) Nov 9
to py4web
ok, still weird,  that line is:

Field('input', 'datetime', requires=IS_DATETIME(format=T('%Y-%m-%d %H:%M:%S'), error_message='must be YYYY-MM-DD HH:MM:SS!'),),

where I took out the default.  and when I refresh the page I get:

11/09/2025 12:30 PM

in the field on the page, for example,,, no matter the format under IS_DATETIME validator.  see?  it is all not close to displaying the proper format.  and I've installed the latest version of py4web, or, "Py4web: 1.20251109.1 on Python 3.13.2 (v3.13.2:4f8bb3947cf, Feb  4 2025, 11:51:10) [Clang 15.0.0 (clang-1500.3.9.4)]" as verified when I rerun py4web.  and I also verified I'm updating and running the correct function under the app.

ok, Lucas

Massimo DiPierro

unread,
Nov 9, 2025, 8:02:20 PM (4 days ago) Nov 9
to py4web
I see the problem and the confusion. Forms in py4web do not work like in web2py by design. Specifically locale for datetime is handled client side and not server side when possible.

The datetime widget renders your datetime like this:
<input class="" id="no_table_input" name="input" type="datetime-local" value="2025-11-09 16:47:45">

So while py4web sends the value in uncode (as intended!) the type="datetime-local" lets the browser choose the correct representation.

In web2py we did not use type="datetime-local" but type="text". 
You can make py4web behave like web2py by replacing the widget for the field called "input" with a barebone simple Widget:

from py4web.utils.form import Form, Widget
...

fields = [
Field("name", length=12, requires=IS_NOT_EMPTY(), default='name',),
Field('input', 'datetime', requires=IS_DATETIME(format=T('%Y-%m-%d %H:%M:%S'), error_message='must be YYYY-MM-DD HH:MM:SS!'), default=datetime.datetime.now()),
Field('duration', 'integer', requires=IS_INT_IN_RANGE(1,1e6), default=200,),
]
form = Form(fields)
form.param.formstyle.widgets["input"] = Widget()

The downside of this is that, like in the case of web2py, the browser is not aware that this is a datetime and does will not provide the correct popup. On mobile specifically it will show you a keyboard instead of a datetime selector. So this is not something I recommend.


Reply all
Reply to author
Forward
0 new messages