将PHP日期格式转换为jQueryUI日期选择器日期格式。

15

[编辑]: 我想人们可能有些难以理解我所说的内容,所以我完全重新编写了我的解释。

我正在开发一个项目,用户可以定义整个网站使用的日期格式,它使用PHP日期格式标准。例如:"年-月-日" 被设置为 "Y-m-d"。

PHP标准使用单字符符号(如 Y,m,d,F,j )来描述日期格式。如文档中所示:http://www.php.net/manual/en/function.date.php

有时用户可以通过jQueryUI Datepicker选择日期。该组件使用类似于yy,y,mm,dd,D,...的代码词来描述其日期格式。http://api.jqueryui.com/datepicker/#utility-formatDate

我希望在PHP和Datepicker中都以相同的格式显示日期。 我的意思是PHP应该按照用户设置的格式输出日期,并且Datepicker应该以相同的格式显示已选择的日期。

鉴于:

  1. 日期格式一定要以“PHP样式”进行描述
  2. 我无法预先知道用户设置了哪种格式

/!\ 这不是如何从已知格式读取/解析/显示日期的问题。

不幸的是,Javascript日期格式描述与PHP中不同。 例如,这两个日期格式在PHP和Javascript中都是等效的,但描述方式不同:

  1. PHP:Y-m-d(用户设置)
  2. Javascript:yy-mm-dd

正如您所看到的,我不能仅使用PHP日期格式来配置Datepicker,因为它可能会被误解或完全无法识别。

在下面的答案中,有人建议创建自己的“日期格式标准转换器”,将每个PHP符号与其在JS日期格式说明中的等效符号匹配。就像这样:
  • Y => yy
  • m => mm
  • d => dd
  • y => y
  • z => o
  • ...
然后用JS符号替换每个PHP符号。这样,“d/m/Y”将神奇地变成“dd/mm/yy”。但也许有人知道另一个适当的方法来让jQueryUI Datepicker理解PHP日期格式标准?

编辑:我撰写了一篇教程,介绍了问题和解决方案。更多阅读:http://tristan-jahier.fr/blog/2013/08/convertir-un-format-de-date-php-en-format-de-date-jqueryui-datepicker


不要将任意日期格式从PHP中发送出去 - 总是以已知的固定格式发送,这样Javascript就会知道该期望什么。不要指望能够“自动处理任何日期格式”,因为由于各种常用格式之间的歧义,这基本上是不可能做到正确的。使用javascript日期选择器的整个重点在于,您的代码永远不应该需要处理任何格式的日期; 作为程序员,您应该完全掌控格式,所以只需选择一个好的格式(通常是yyyy-mm-dd)并坚持使用它。 - Spudley
我理解你的想法。但这并不是我的问题。 实际上,我希望用户看到由Datepicker显示的日期与以下格式相同: echo $date->format("any_format"); - Tristan Jahier
vlttp:这是一个让我疯狂的事情,因为过去20年我使用的所有其他编程语言都使用单个字符来表示单个数字,使用双字符来表示双位数字,并在需要时填充零。为什么PHP(几乎在所有其他方面都很完美)在这一点上要如此不同呢?而且,在本身已经相当混乱的领域(日期)内! - motoDrizzt
5个回答

35
我选择了一种残酷的方法:逐个转换日期格式中的符号。我编写了一个“不那么愚蠢”的代码片段。
/*
 * Matches each symbol of PHP date format standard
 * with jQuery equivalent codeword
 * @author Tristan Jahier
 */
function dateformat_PHP_to_jQueryUI($php_format)
{
    $SYMBOLS_MATCHING = array(
        // Day
        'd' => 'dd',
        'D' => 'D',
        'j' => 'd',
        'l' => 'DD',
        'N' => '',
        'S' => '',
        'w' => '',
        'z' => 'o',
        // Week
        'W' => '',
        // Month
        'F' => 'MM',
        'm' => 'mm',
        'M' => 'M',
        'n' => 'm',
        't' => '',
        // Year
        'L' => '',
        'o' => '',
        'Y' => 'yy',
        'y' => 'y',
        // Time
        'a' => '',
        'A' => '',
        'B' => '',
        'g' => '',
        'G' => '',
        'h' => '',
        'H' => '',
        'i' => '',
        's' => '',
        'u' => ''
    );
    $jqueryui_format = "";
    $escaping = false;
    for($i = 0; $i < strlen($php_format); $i++)
    {
        $char = $php_format[$i];
        if($char === '\\') // PHP date format escaping character
        {
            $i++;
            if($escaping) $jqueryui_format .= $php_format[$i];
            else $jqueryui_format .= '\'' . $php_format[$i];
            $escaping = true;
        }
        else
        {
            if($escaping) { $jqueryui_format .= "'"; $escaping = false; }
            if(isset($SYMBOLS_MATCHING[$char]))
                $jqueryui_format .= $SYMBOLS_MATCHING[$char];
            else
                $jqueryui_format .= $char;
        }
    }
    return $jqueryui_format;
}

这个函数处理PHP和Datepicker日期格式标准之间的所有常见代码字。

此外,我增加了对字符转义的支持:

d m \o\f Y 变成 dd mm 'of' yy

你仍然可能会遇到一些符号,比如 'W'、'L',它们没有被 Datepicker 处理的等价物。


1
不用客气。;-) 如果您觉得这个答案有用和相关,请点赞。 - Tristan Jahier
你好@TristanJ,上面的代码片段似乎无法支持时间。这是什么原因?两个标准之间是否存在不一致,还是你只是想创建日期格式转换器? - gen
嗨@gen。这是因为我正在使用jQuery UI的“Datepicker”(即:http://jqueryui.com/datepicker),它不支持时间。这就是为什么我从来没有想过那个。但是你应该能够轻松地添加时间支持。只需查找您的“日期和时间选择器”支持的符号,并报告$SYMBOLS_MATCHING数组中的更改即可。 - Tristan Jahier

4

您不能将与 PHP 相同的格式用于 datepicker。

因为 PHP 的日期格式只使用单个字母代码,所以最好只需采用 PHP 日期格式,并将每个代码替换为 jQuery datepicker 格式中相应的值,例如:

$PHPFormatOptions = array('y', 'Y', 'm', 'd');
$JSFormatOptions = array('yy', 'yyyy', 'mm', 'dd'); // and so on
$JSFormat = str_replace($PHPFormatOptions, $JSFormatOptions, $PHPFormat);

那么,您建议创建一种将每个符号匹配在一起的字典? - Tristan Jahier
我希望没有歧义的情况。 - Tristan Jahier

2
这是解决方案:
function datepicker_format($format) {
        static $assoc = array(
            'Y' => 'yyyy',
            'y' => 'yy',
            'F' => 'MM',
            'm' => 'mm',
            'l' => 'DD',
            'd' => 'dd',
            'D' => 'D',
            'j' => 'd',
            'M' => 'M',
            'n' => 'm',
            'z' => 'o',
            'N' => '',
            'S' => '',
            'w' => '',
            'W' => '',
            't' => '',
            'L' => '',
            'o' => '',
            'a' => '',
            'A' => '',
            'B' => '',
            'g' => '',
            'G' => '',
            'h' => '',
            'H' => '',
            'i' => '',
            's' => '',
            'u' => ''
        );

        $keys = array_keys($assoc);

        $indeces = array_map(function($index) {
            return '{{' . $index . '}}';
        }, array_keys($keys));

        $format = str_replace($keys, $indeces, $format);

        return str_replace($indeces, $assoc, $format);
    }

由于在 needles 和其替换值中重复,所以魔法双 str_replace 调用会发生,这就是为什么字符串会被替换两次的原因。
m/d/Y 

变成

{{3}}/{{5}}/{{1}}

然后,这些嵌套将被实际替换值所替换:

mm/dd/yy

1

我不确定我是否完全理解了你的意思,但这真的不应该是一个问题。你可以使用DateTime::createFromFormat(有关此内容请参阅php文档)来解析前端输入,或者使用JSON。
由于JSON有一种被接受的标准格式化日期字符串的方法,因此您可以将输入日期的JSON字符串版本传递给PHP,并在服务器端对其进行json_decode。这两种解决方案都对您开放,尽管我认为第一种更容易在您的情况下实现。

如果您想要能够选择双方的格式,则DateTime对象绝对是您所需要的:

$date = new DateTime();
echo $date->format('Y-m-d').' <==> '.$date->format('y-M-j');
$postDate = $date->createFromFormat('y-m-d',$_POST['submitDate']);
echo $postDate->format('Y-m-d');

格式在我链接的页面上有解释。

我认为这不是关于解析输入本身的问题,而是关于日期格式字符串以及在PHP的日期格式字符串和jQuery的日期格式字符串之间进行转换,即字面上在Y-m-dyy-mm-dd之间进行转换。 - pilsetnieks
那么第一种选择是最好的方法,我只需要添加_查看DateTime对象_。 - Elias Van Ootegem
实际上,我没有问题从给定的日期格式中解析日期。问题是要让Datepicker接受我从PHP获取的日期格式。 - Tristan Jahier
@TristanJ:那么,要么使用DateTime对象并向日期选择器发送不同的格式,要么使用json_encode,因为JSON编码的日期是标准格式,JS会将其转换为日期对象。 - Elias Van Ootegem

-3

好的,对于您来说最好的解决方案是使用time()将所有内容存储在您的网站上。

据我所知,日期选择器可以设置为与PHP时间戳一起使用。

dateFormat : 'yy-mm-dd',

编辑:

为什么要以 Y-m-d 的格式存储日期? 应该以时间戳或整数形式存储。


这不是关于日期转换或日期存储的问题。 我希望日期选择器能够处理与网站显示的相同日期格式标准。但对于任何标准,我都无法硬编码它。 - Tristan Jahier

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接