locale specific dateformatting buggy?

时间:2015-09-04 09:48:30

标签: coldfusion date-format cfml

我们已经遇到了一年多的日期格式问题。我们的数据库中有欧盟格式(dd / mm / yyyy),我们也希望在我们的网站上输出。问题是我们通过coldfusion的日期格式化函数运行日期,以确保我们总是以相同的方式输出日期(以及其他原因)。

这就是出错的地方。下面的代码输出2个不同的日期,我们期望相同的日期。

<cfoutput>
    #LSDateFormat('01/02/2015', 'dd/mm/yyyy', 'nl_BE')# <br />
    #LSDateTimeFormat('01/02/2015', 'dd/mm/yyyy HH:nn', 'nl_BE')#
</cfoutput>

// output
// 01/02/2015
// 02/01/2015 00:00

我尝试过trycf.com,使用所有不同的可用引擎。 请向我解释我在这里做错了什么。或者告诉我这是一个没有人提到的错误。但我希望我在这里错了..

2 个答案:

答案 0 :(得分:3)

我认为你误解了'格式'功能。它们专为演示而设计。他们的目的是将日期对象转换为字符串:即LSDateTimeFormat (date , mask)。 'mask'用于确定 output 字符串的外观,而不是解析输入。请注意,如果您传入日期 object ,而不是字符串,它的工作方式与您预期的完全相同?结果是01/02/2015 00:00

  dateObject = createDate(2015,2,1);
  writeDump("dateObject = "& LSDateTimeFormat(dateObject, 'dd/mm/yyyy HH:nn', 'nl_BE'));

是的,CF允许你变懒,而是传入一个字符串。但是,CF必须仍然可以将该字符串转换为日期对象,然后才能应用掩码 - 而且您无法控制CF的执行方式。当您使用字符串时,您基本上将该字符串的解释完全保留为CF.在这种情况下,CF根据美国日期规则(即月份优先)解释模糊字符串“01/02/2015”。这将产生于2015年1月2日。因此掩码dd/mm/...的输出为 02/01 / 2015 00:00。所以从本质上讲,你的代码真正做的是:

     // parse string according to U.S. rules - mm/dd/yyyy
     HowCFInterpretsYourString = parseDateTime(dateString);
     LSDateTimeFormat(HowCFInterpretsYourString, 'dd/mm/yyyy HH:nn', 'nl_BE');

<强>结果:

     HowCFInterpretsYourString = {ts '2015-01-02 00:00:00'} <=== January 2nd 
     LSDateTimeFormat          = 02/01/2015 00:00           <=== Day = 2, Month = 1

如果您不希望CF为您执行解释,请传入日期对象 - 而不是字符串。

至于为什么LSDateFormat的行为似乎与LSDateTimeFormat不一致,我不知道。但是,字符串含糊不清。因此,当您使用它们而不是日期对象时,那么......期待意外。

  

我们应该先转换为正确的日期对象,然后使用普通的dateFormat方法进行格式化。

仅仅因为您只使用格式函数输出数字日期部分,并不意味着他们所做的全部;-)格式函数也输出名称,这是特定于语言环境的。例如,"MMMMM"可能会生成“九月”或“七月”,具体取决于当前的区域设置。还有其他区域特定规则,例如“月”和“日”的放置以及名称的确切大写。标准Date/TimeFormat functions 始终使用美国约会惯例。而LSDateTimeFormat使用提供的任何语言环境。在这种特定情况下,没有太大区别,因为您只输出数字日期部分:

数字日期部分(仅限)

dateObject = createDate(2015,2,1);
writeDump("LSDateTimeFormat = "& LSDateTimeFormat(dateObject, 'dd/mm/yyyy', 'nl_BE'));
writeDump("DateTimeFormat = "& DateTimeFormat(dateObject, 'dd/mm/yyyy'));

结果:

LSDateTimeFormat = 01/02/2015 
DateTimeFormat = 01/02/2015 

但是,对于其他格式,存在很大差异。日期对象可能没有绑定到区域设置,但日期的字符串表示是..所以这两个函数不可互换。

日期名称:

 dateObject = createDate(2015,2,1);
 writeDump("LSDateTimeFormat = "& LSDateTimeFormat(dateObject, 'full', 'nl_BE'));
 writeDump("DateTimeFormat = "& DateTimeFormat(dateObject, 'full'));

结果:

LSDateTimeFormat = zondag 1 februari 2015 0.00 u. UTC 
DateTimeFormat = Sunday, February 1, 2015 12:00:00 AM UTC 
  

“我们的数据库中的欧盟格式(dd / mm / yyyy)”

不确定你的意思。日期/时间对象没有格式。您的IDE可能会将它们显示为人性化的字符串,但日期值本身将存储为数字。根据您描述的内容,听起来要么将值存储为字符串,要么将其转换为字符串,这可以解释结果。相反,将值存储在日期/时间列中,然后检索它们并将它们“原样”传递给函数,它应该可以正常工作。

答案 1 :(得分:0)

我使用英语(美国)语言环境约定,所以我可以使用ParseDateTime(),DateFormat()或DateTimeFormat()...但由于你的日期是UE,你必须在表示日期的字符串上使用LSParseDateTime()结果应该是一致的

<cfset D = "01/02/2015">
<cfoutput>
0. #D#<br />
1. #DateFormat(D)#<br />
2. #ParseDateTime(D)# (Parse default US)<br />
3. #LSParseDateTime(D,'en_GB')# (Parse en_GB)<br />
4. #LSDateFormat(D, 'dd/mm/yyyy', 'nl_BE')# (no parsing, default US)<br />
5. #LSDateTimeFormat(D, 'dd/mm/yyyy HH:nn', 'nl_BE')# (no parsing, default US)<br />
6. #LSDateFormat(ParseDateTime(D), 'dd/mm/yyyy', 'nl_BE')# (parsed as default US)<br />
7. #LSDateTimeFormat(ParseDateTime(D), 'dd/mm/yyyy HH:nn', 'nl_BE')# (parsed as default US)<br />
8. #LSDateFormat(LSParseDateTime(D,'en_GB'), 'dd/mm/yyyy', 'nl_BE')# (parsed as en_GB locale)<br />
9. #LSDateTimeFormat(LSParseDateTime(D,'en_GB'), 'dd/mm/yyyy HH:nn', 'nl_BE')# (parsed as en_GB locale)<br />
</cfoutput>

文本字符串“01/02/2015”的结果:

0. 01/02/2015
1. 02-Jan-15
2. {ts '2015-01-02 00:00:00'} (Parse default US)
3. {ts '2015-02-01 00:00:00'} (Parse en_GB)
4. 01/02/2015 (no parsing, default US)
5. 02/01/2015 00:00 (no parsing, default US)
6. 02/01/2015 (parsed as default US)
7. 02/01/2015 00:00 (parsed as default US)
8. 01/02/2015 (parsed as en_GB locale)
9. 01/02/2015 00:00 (parsed as en_GB locale)

您可以使用SQL重新格式化查询数据以标准化美国语言环境约定: http://www.sql-server-helper.com/tips/date-formats.aspx

SELECT CONVERT(VARCHAR(10), DateField, 101) AS USDate_MMDDYYYY

无论哪种方式,我建议您创建一个UDF,以便您可以在一个地方修改此规则,以防您需要进行任何未来的修改。