如何正确呈现 ar-SA 日期和时间字符串
How to correctly render a ar-SA date and time string
所以,我有一个 DateTime 值,我需要使用 ar-SA 区域性(使用公历)将其呈现出来。
我想使用的格式是 dd-MMM-yyyy HH:mm。
我目前正在使用它来格式化它 -
dateTimeValue.ToString("dd-MMM-yyyy HH:mm", culture)
在 en-GB 中,我会看到 -
06-Jun-2017 16:49
在ar-SA中,当我使用相同的方法时,我看到-
06-يونيو-2017 16:49
现在,据我所知,我认为是 RTL 字符串导致了问题,因为它总是在右侧。
如何在 RTL 中正确呈现此日期?
var dt = DateTime.Parse("31/1/2016 12:00 AM", CultureInfo.GetCultureInfo("ar-SA"));
// Throws FormatException
并且您无法使用 ar-SA 区域性解析此字符串,因为此区域性使用 ص
作为 AMDesignator,因为它使用 UmAlQuraCalendar 而不是 GregorianCalendar。
您可以使用 InvariantCulture(它使用 AM 作为 AMDesignator 并使用 GregorianCalendar)代替 DateTime.ParseExact 方法并准确指定它的格式。
string s = "31/1/2016 12:00 AM";
DateTime dt = DateTime.ParseExact(s, "dd/M/yyyy hh:mm tt",CultureInfo.InvariantCulture);
参考here。有人或多或少遇到了与您相同的问题,这似乎解决了错误。希望这有帮助。
渲染它去看看 and 。他们似乎对可能能够解决您的问题的渲染有类似的问题。
是的,经过一番挖掘,我设法找到了一个可行的解决方案。
即使我的问题最初是关于 ar-SA,它也适用于任何从右到左的文化。
我最终使用 unicode 字符来明确说明字符串的哪些部分是从左到右和从右到左的。
因此,使用常量 -
private const char LeftToRightCharacter = (char)0x200E;
private const char RightToLeftCharacter = (char)0x200F;
然后我可以构建一个日期字符串,如下所示 -
if (culture.TextInfo.IsRightToLeft)
{
return
LeftToRightCharacter +
date.ToString("yyyy-", culture) +
RightToLeftCharacter +
date.ToString("MMM", culture) +
LeftToRightCharacter +
date.ToString("-dd", culture);
}
return date.ToString("dd-MMM-yyyy", culture);
...其中 culture 是 CultureInfo(DateTimeFormat.Calendar 设置为 new GregorianCalendar()),date 是 DateTime。
因此,对于日期 06-Jun-2017,在 en-GB 我得到 -
06-Jun-2017
在 ar-SA 中我得到 -
2017-يونيو-06
既然我已将其作为字符串,我可以在任一侧添加时间(如果区域性是 RTL,则在左侧,如果区域性是 LTR,则在右侧)。
了解 Unicode 如何处理这些字符以及我本可以使用的其他字符非常有用 - http://www.unicode.org/reports/tr9/
CultureInfo CurrentCulture = CultureInfo.GetCultureInfo("ar-AE");
string text = DateTime.Now.ToString("yyyy MMMM dd", CurrentCulture);
ar-SA 短日期模式是:
- d[U+200F] /M [U+200F]/yyyy g for dotnet v6.0.1
- MM/dd/yyyy for date-fns/locale/ar-SA v4.26
U+200F 是Right-To-Left标记字符。
如果打印出来,它显示为“d /M /yyyy g”。
不确定最后的“g”是什么,也许是时代(如果不是“G”?)
此外,date-fns.format() 函数不接受“g”并引发错误。
open System
open System.Globalization
open System.IO
let culture = CultureInfo.GetCultureInfo("ar-SA")
let pattern = culture.DateTimeFormat.ShortDatePattern
let date1 = DateTime(2017, 6, 6).ToString(pattern)
let date2 = DateTime(2017, 6, 6).ToString(pattern, culture)
use writer = File.CreateText("C://temp//ar-SA date.txt")
writer.WriteLine $"Short date1: {date1}"
writer.WriteLine $"Short date2: {date2}"
结果,从记事本++复制粘贴:
Short date1: 6/6/2017 AD <- bad rendering here in the post
Short date2: 11/9/1438 بعد الهجرة <- bad rendering here in the post
在记事本++中,“6”和“11”出现在正确的位置:
所以,“错误”位置似乎真的是日期打印位置的问题(HTML,文本文件...)。
当您更改当前线程的文化时,它会正确使用回历,因此年份为 1438。
我在模式中添加了一个额外的 RLM 标记(一天之前):
" [U+200F]d[U+200F] /M[U+200F] /yyyy g"
它在 notepad++ 和 copy-pasted 中都是正确的:
Short date3: 11/9/1438 بعد الهجرة
所以,我有一个 DateTime 值,我需要使用 ar-SA 区域性(使用公历)将其呈现出来。
我想使用的格式是 dd-MMM-yyyy HH:mm。
我目前正在使用它来格式化它 -
dateTimeValue.ToString("dd-MMM-yyyy HH:mm", culture)
在 en-GB 中,我会看到 -
06-Jun-2017 16:49
在ar-SA中,当我使用相同的方法时,我看到-
06-يونيو-2017 16:49
现在,据我所知,我认为是 RTL 字符串导致了问题,因为它总是在右侧。
如何在 RTL 中正确呈现此日期?
var dt = DateTime.Parse("31/1/2016 12:00 AM", CultureInfo.GetCultureInfo("ar-SA"));
// Throws FormatException
并且您无法使用 ar-SA 区域性解析此字符串,因为此区域性使用 ص
作为 AMDesignator,因为它使用 UmAlQuraCalendar 而不是 GregorianCalendar。
您可以使用 InvariantCulture(它使用 AM 作为 AMDesignator 并使用 GregorianCalendar)代替 DateTime.ParseExact 方法并准确指定它的格式。
string s = "31/1/2016 12:00 AM";
DateTime dt = DateTime.ParseExact(s, "dd/M/yyyy hh:mm tt",CultureInfo.InvariantCulture);
参考here。有人或多或少遇到了与您相同的问题,这似乎解决了错误。希望这有帮助。
渲染它去看看
是的,经过一番挖掘,我设法找到了一个可行的解决方案。
即使我的问题最初是关于 ar-SA,它也适用于任何从右到左的文化。
我最终使用 unicode 字符来明确说明字符串的哪些部分是从左到右和从右到左的。
因此,使用常量 -
private const char LeftToRightCharacter = (char)0x200E;
private const char RightToLeftCharacter = (char)0x200F;
然后我可以构建一个日期字符串,如下所示 -
if (culture.TextInfo.IsRightToLeft)
{
return
LeftToRightCharacter +
date.ToString("yyyy-", culture) +
RightToLeftCharacter +
date.ToString("MMM", culture) +
LeftToRightCharacter +
date.ToString("-dd", culture);
}
return date.ToString("dd-MMM-yyyy", culture);
...其中 culture 是 CultureInfo(DateTimeFormat.Calendar 设置为 new GregorianCalendar()),date 是 DateTime。
因此,对于日期 06-Jun-2017,在 en-GB 我得到 -
06-Jun-2017
在 ar-SA 中我得到 -
2017-يونيو-06
既然我已将其作为字符串,我可以在任一侧添加时间(如果区域性是 RTL,则在左侧,如果区域性是 LTR,则在右侧)。
了解 Unicode 如何处理这些字符以及我本可以使用的其他字符非常有用 - http://www.unicode.org/reports/tr9/
CultureInfo CurrentCulture = CultureInfo.GetCultureInfo("ar-AE");
string text = DateTime.Now.ToString("yyyy MMMM dd", CurrentCulture);
ar-SA 短日期模式是:
- d[U+200F] /M [U+200F]/yyyy g for dotnet v6.0.1
- MM/dd/yyyy for date-fns/locale/ar-SA v4.26
U+200F 是Right-To-Left标记字符。
如果打印出来,它显示为“d /M /yyyy g”。
不确定最后的“g”是什么,也许是时代(如果不是“G”?)
此外,date-fns.format() 函数不接受“g”并引发错误。
open System
open System.Globalization
open System.IO
let culture = CultureInfo.GetCultureInfo("ar-SA")
let pattern = culture.DateTimeFormat.ShortDatePattern
let date1 = DateTime(2017, 6, 6).ToString(pattern)
let date2 = DateTime(2017, 6, 6).ToString(pattern, culture)
use writer = File.CreateText("C://temp//ar-SA date.txt")
writer.WriteLine $"Short date1: {date1}"
writer.WriteLine $"Short date2: {date2}"
结果,从记事本++复制粘贴:
Short date1: 6/6/2017 AD <- bad rendering here in the post
Short date2: 11/9/1438 بعد الهجرة <- bad rendering here in the post
在记事本++中,“6”和“11”出现在正确的位置:
所以,“错误”位置似乎真的是日期打印位置的问题(HTML,文本文件...)。
当您更改当前线程的文化时,它会正确使用回历,因此年份为 1438。
我在模式中添加了一个额外的 RLM 标记(一天之前):
" [U+200F]d[U+200F] /M[U+200F] /yyyy g"
Short date3: 11/9/1438 بعد الهجرة