When using text fields for date input, the field has a input format that date_text_input_value uses to parse the input. If the input does not match the format exactly, strtotime is used as a fallback.

At least for my setup (when using Site's timezone which is not UTC), the strtotime fallback gives unexpected results, since it uses UTC when "completing" the date. If the format is "Y-m-d H:i" and the user only enters "2008-05-31" (thus no time) I want the time to be set to "00:00". The current code sets it to 00:00 in UTC, not the Site's timezone. So when the date is displayed it is "2008-05-30 22:00" if my timezone was +02:00.

The attached patch solve my issue. If anyone did like the current behaviour -- where dates that match the format (includes time) are parsed in one timezone and dates that do not completely match the format (no time) are parsed in UTC -- then they will not like this patch. What do you think about it? Are there other side effects?

The patch assumes that $element['#date_timezone'] always exists, if that is false perhaps a plain strtotime should be kept as additional fallback?

Some other info: Tested using date (not datestamp) in text selectors. All possible timezone settings tested (site, none, utc, date, user) except possible user since user's don't have custom timezones at my site. My timezone is Europe/Stockholm.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

KarenS’s picture

Status: Needs review » Fixed

It took me a while but I finally got back to this. I agree, this is a good idea. I brought the patch up to date and committed it. Thanks!

Anonymous’s picture

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for two weeks with no activity.

emok’s picture

Title: Use timezone for text input that dit not fit the format » Accept text input that omits hour & minute, even if the format expects it
Version: 6.x-2.x-dev » 6.x-2.0-beta4
Priority: Minor » Normal
Status: Closed (fixed) » Needs review
FileSize
509 bytes

Hi again. The following remaining issue took me a while to note, since I did not use my site much the previous week. My description is slightly different now, but actually the bug is as bad as before.
When the expected format is "Y-m-d H:i" and the user enters a date without time, like "2008-05-31", the 6.x-2.0-beta4 version of Date falls back to use "now" (at least on PHP 4.3.11) which is completely wrong.

It seems the above patch was changed before the beta4-release and still does not cover the case where time is missing. I haven't re-checked on PHP5, but I think it is rather obvious that when the statement date_is_valid($value) == false it is a bad idea to use the $value variable and continue trying to parse it. In my case the lack of hour & minute means $value is null/false, so it is not strange
$date = date_make_date($value, $element['#date_timezone']); falls back to use "now".

Instead I re-propose the code of the old patch, that starts over from the $input and uses a more liberal parser:
$date = date_create($input, timezone_open($element['#date_timezone']));. Re-rolled patch attached.

It also works to make the smaller change of $value to $input, which gives
$date = date_make_date($input, $element['#date_timezone']);. Perhaps you like that better?

Does my version break anything else? Maybe a check can be added so that $input is used if empty($value) while if there is something in $value it would be used?

KarenS’s picture

Version: 6.x-2.0-beta4 » 6.x-2.x-dev

The beta4 version is older than the -dev version, so if we're fixing something broken we're working in -dev, not in beta4. We don't patch versions, we only patch -dev. And we test if things are working by looking at -dev, so talking about the 'beta4 version falls back to...' is meaningless, the beta4 version is issued once and never changes.

I'm unavailable to work on any of this until later today, when I'll try to sort out what, if anything of this applies to the -dev version.

KarenS’s picture

Status: Needs review » Postponed (maintainer needs more info)

I can't see any problem using the latest code in getting the right values stored if you leave hour and minute blank in date_select elements. If you still see problems using the latest -dev code, I need more information about how to replicate your problem.

I understand your question about why date_make_date() defaults to 'now', but it's to prevent millions of errors I was seeing when the input didn't create a date object. The code has been cleaned up a lot since then, so it may be that I can get rid of that now, but I haven't yet.

But with or without that change, I get the right results when I leave hours and minutes empty, they always default to 00:00:00.

emok’s picture

Status: Needs review » Postponed (maintainer needs more info)
FileSize
538 bytes

Hi again!
There were some misunderstandings about my comment #3. I made a mistake in using a beta rather than DEV version. Then apparently my English was unclear too: By "fall back" I did not mean a regression between code versions, but the contents of the else-block that date_text_input_value falls back to use when date_is_valid($value)==false.

In #5 you (KarenS) talk about date_select. Perhaps that is also a misunderstanding, because what I am discussing is the text input field where the user enters a single string.

How to reproduce:

  1. Have a date field where the format & granularity is set to include hour and minute, and the widget type type is text field. Default value blank. (I also use mandatory end date but that shouldn't matter.) Use it on some node type.
  2. Edit a node of the type with date. Enter "2008-12-15" (not today's date) in the text field for the date. Submit.
  3. Now the date is parsed as if nothing was entered, thus defaulting to now().
  • The problem is not the default value, but the fact that a string "almost" matching the format is considered invalid and ignored (treated as empty string).
  • I want the date to be parsed as "2008-12-15 00:00".

Based on the current (20 september) DEV we're down to a single variable name that I would like to change now.
Motivation: when we end up in the else-clause that's because the first parser failed to accept the date and date_is_valid($value)==false. When that happens, $value is no longer the incomplete date but NULL (you can add print "null?=".is_null($value); in the else-clause to check). Therefore $value cannot be used to feed the more generous parser in the else statement (it would be parsing a NULL-value), we need to use the original input string $input.

emok’s picture

Status: Postponed (maintainer needs more info) » Needs review

Forgot to change the status previously.

KarenS’s picture

Status: Postponed (maintainer needs more info) » Fixed

Ah! I misunderstood. OK, I'm committing this change now.

Anonymous’s picture

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for two weeks with no activity.

KarenS’s picture

Status: Closed (fixed) » Active

I'm going to have to remove the strtotime handling, both the original way it was done and later handling, because I am running into too many situations where you input garbage and don't get any error generated and it either creates the current date or some other wrong value. Basically, no validation error is ever generated, no matter what you input, it's just way too forgiving and ends up silently converting all kinds of values to 'now' (see #324794: Text date field always stores current date).

I'll reopen this for more thought about how this could be done without creating that problem.

KarenS’s picture

Category: bug » feature

This is really more of a feature request.

mattman’s picture

Karen, I'd like to suggest adding the raw strtotime evaluation as a widget.

My personal use case is such that I offer a quarterly magazine. It's extremely nice to be able to simply enter "3 months" (from today) rather than have to calculate out. By offering a widget, which would remove the format validation and use raw strtotime, this would be possible.

Maybe a widget named something like the following...

    'date_text_raw' => array(
      'label' =>  t('Text Field without validation'),
      'field types' => array('date', 'datestamp', 'datetime'),
      'multiple values' => CONTENT_HANDLE_CORE,
      'callbacks' => array(
        'default value' => CONTENT_CALLBACK_CUSTOM,
        ),
      ),

Matt from GotDrupal.com

vikingjs’s picture

Worth noting that at this time there are many places in the documentation and in the UI that state explicitly that strtotime is invoked; in the current release that is not true. Not very user-friendly.

I too would like fields to validate with only a subset of the date information in the format string. If I find the magic bullet I will let you know.

DamienMcKenna’s picture

Status: Active » Closed (won't fix)

Unfortunately the Drupal 6 version of the Date module is no longer supported. That said, we appreciate that you took time to work on this issue. Should this request still be relevant for Drupal 7 please feel free to reopen it. Thank you.