特定于语言环境的日期格式错误?
locale specific dateformatting buggy?
我们 运行 陷入日期格式问题已有一年多了。我们的数据库中有一个欧盟格式 (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,使用所有不同的可用引擎。
请向我解释我在这里做错了什么。或者告诉我这是一个从未有人提到过的错误。但我宁愿我在这里错了..
我使用英语 (U.S.) 语言环境约定,因此我可以使用 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,这样您就可以在一个地方修改此规则,以备日后需要进行任何修改时使用。
我认为您误解了 'format' 函数。它们专为展示而设计。他们的目的是将一个日期object转换成一个字符串:即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会根据U.S解释歧义字符串“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不一致,我不知道。但是,字符串是不明确的。因此,当您使用它们而不是日期对象时,嗯......期待意外。
We should just convert to the correct date object first and then format using the normal dateFormat method.
仅仅因为您只使用格式函数来输出数字日期部分,并不意味着它们就是这样做的;-)格式函数还输出特定于区域设置的名称。例如,"MMMMM"
可能会生成 "September" 或 "septiembre",具体取决于当前语言环境。还有其他特定于区域的规则,例如 "month" 和 "day" 的位置以及名称的准确大写。标准 Date/TimeFormat functions always use U.S. date conventions. Whereas 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
"EU formatting in our database (dd/mm/yyyy)"
不确定你的意思。 Date/time 对象没有格式。您的 IDE 可能将它们显示为人类友好的字符串,但日期值本身存储为数字。根据您的描述,听起来这些值要么存储为字符串,要么正在转换为字符串,这可以解释结果。相反,将值存储在 date/time 列中,然后检索它们并将它们传递给函数 "as is",它应该可以正常工作。
我们 运行 陷入日期格式问题已有一年多了。我们的数据库中有一个欧盟格式 (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,使用所有不同的可用引擎。 请向我解释我在这里做错了什么。或者告诉我这是一个从未有人提到过的错误。但我宁愿我在这里错了..
我使用英语 (U.S.) 语言环境约定,因此我可以使用 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,这样您就可以在一个地方修改此规则,以备日后需要进行任何修改时使用。
我认为您误解了 'format' 函数。它们专为展示而设计。他们的目的是将一个日期object转换成一个字符串:即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会根据U.S解释歧义字符串“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不一致,我不知道。但是,字符串是不明确的。因此,当您使用它们而不是日期对象时,嗯......期待意外。
We should just convert to the correct date object first and then format using the normal dateFormat method.
仅仅因为您只使用格式函数来输出数字日期部分,并不意味着它们就是这样做的;-)格式函数还输出特定于区域设置的名称。例如,"MMMMM"
可能会生成 "September" 或 "septiembre",具体取决于当前语言环境。还有其他特定于区域的规则,例如 "month" 和 "day" 的位置以及名称的准确大写。标准 Date/TimeFormat functions always use U.S. date conventions. Whereas 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
"EU formatting in our database (dd/mm/yyyy)"
不确定你的意思。 Date/time 对象没有格式。您的 IDE 可能将它们显示为人类友好的字符串,但日期值本身存储为数字。根据您的描述,听起来这些值要么存储为字符串,要么正在转换为字符串,这可以解释结果。相反,将值存储在 date/time 列中,然后检索它们并将它们传递给函数 "as is",它应该可以正常工作。