Flash Player中的flash.globalization包(part7):格式化日期和时间

数千年来,各种文明都在关注计时问题,并且形成了至今仍在使用几种日历(several calendars)。相对于数,日期和时间的书面表示在不同的文化之间有很大的差异。幸运的是,在DateTimeFormatter类的帮助下,您的应用程序可以很容易地以对大多数用户熟悉的方式对它们进行显示。

文化敏感的日期和时间格式

不同操作系统对日历的支持差异很大。在这个时候,只有公历(Gregorian calendar)完全被flash.globalization包支持。

每一个数量级(年、月、日)都可以以不同的方式表示:全名、缩写或数字(零填充(zero-padded)或不填充)。这些选择由环境(circumstances)决定。然而,由于文化偏好使的它们更加复杂。

月份的名字和星期几的名字必须自然地被翻译成用户的语言。但是使用全数字格式您也必须注意区域的问题。

例如,考虑2009年8月的第七天这一日期(见表3)。一位美国用户通常会先写月份,其次是天,然后是年。相比之下,英国的用户通常会先写日,其次是月,最后是年。一位加拿大公务员和一个日本用户先写年,其次是月,最后天。显然,如果使用的约定与用户期望的不同,那么严重的混淆就很可能随之而来!
表3.日期格式示例

在一天中的时间的书写形式也会有一些不同,最明显的是使用24或12小时制。在后一种情况中,半天由一个缩写标示的(例如,AM(上午)PM(下午)),这种缩写从一种语言到另一种语言也是不同的。

格式化器能以三种标准格式表示日期和时间(LONG, MEDIUM, and SHORT(长、中、短)),并且还可以使用一个CUSTOM(自定义)模式。每个stock格式所使用的实际模式可能会随操作系统不同而有某种程度的不一样。相比之下,自定义模式给了您对格式的完全控制权,但请记住,使用它们就阻止了格式化器自动选择适合的区域模式了(对于用户亦然)。表4显示一个您可能会得到的结果的示例。
表4.日期和时间格式示例

中立依然是更好的

正如数字和货币金额,明智的做法是使用最中立的表示方法进行日历值的永久性存储(在一个数据库或文件)。当应用程序直接与用户交互时,使用日期和时间格式化器处理。如果您必须存储一个文本表示,考虑使用Date类的toString()方法或toUTCString()方法,它们输出一个基于ANSI C的asctime()函数的文本表示。接着,您可以使用Date类的parse()方法来将文本转换回一个Date对象。或者,您可能愿意(或是需要)创建您自己的格式化器和解析器函数来使用(例如)一个ISO 8601的profile,就像在W3 Consortium中的Date and Time Formats描述的那个。

当考虑互操作性时,不要忘记,时区和夏令时(Daylight Saving Time)也起着作用。如果您的目标是用一个时间戳标记一个文件或事件(例如,一个传输(transmission))以便随后可以进行时,UTC时间通常是最好的。如果本地时间(如人们在时钟上看到的)是重要的,那么它应被存储,随着使用的时区指示一起。例如,一个按当地时间安排的未来事件的计算所得的时间可能变成错误的,如果夏令时的规则变化的话。

使用DateTimeFormatter类

如同数字和日期一样,您首先创建格式化器,这一次是实例化类DateTimeFormatter。指定一个区域标识符或使用默认的区域:
import flash.globalization;   var dateFormatter:DateTimeFormatter = new  DateTimeFormatter(selectedLocale);

在这里,一个备用的区域可能被选中。更多有关此的信息请阅读关于NumberFormatter类的讨论,在“Selecting a locale”一节。

默认情况下,长型的(long)日期和时间格式将被选中。您可以通过向构造函数传递额外的参数,或者随时使用setDateTimeStyle()方法来改变:
//设置格式化器使只显示日期(没有时间),以medium风格。
 dateFormatter.setDateTimeStyle(DateTimeStyle.MEDIUM,  DateTimeStyle.NONE);

不用每次改变格式化器的配置,考虑一次实例化几个格式化器并重复使用多次:

var dateFormatter:DateTimeFormatter =   new DateTimeFormatter(selectedLocale,   DateTimeStyle.MEDIUM,   DateTimeStyle.NONE); var timeFormatter:DateTimeFormatter =   new DateTimeFormatter(selectedLocale,   DateTimeStyle.NONE,   DateTimeStyle.MEDIUM);

现在您可以格式化您的第一个日期了: var now:Date = new Date(); var todayText:String =  dateFormatter.format(now);

日期和时间格式化器将自动地使用通过区域标识符所指定的语音转换来的月份和星期几的名字。根据平台的不同,当模式将天放在月份名称的邻近位置时,后者的所有格形式将自动地根据语音需要而使用(俄语、波兰语、希腊语等)。例如,请注意Май俄语的五月)采用мая的所有格形式,如在“5th of May 2009”中那样(见图3)。

图3. 月份名称的所有格

如果您需要绘制一个自定义日历,您可以从格式化器来获得这些翻译好的名称,使用方法getMonthNames()和getWeekdayNames()。根据操作系统的不同,全名和缩写形式可能可用(选择来自DateTimeNameStyle类的常量中您所需要那个)。请求DateTimeNameContext.FORMAT格式,如果您打算将月份名称与月中的哪一天一起使用(所有格形式将会被返回,如果它存在的话),要么,请求 DateTimeNameContext.STANDALONE格式,如果您想自己显示他们(例如,以月历形成页面的标题)。此外,getFirstWeekday()方法将返回选定的区域的一个星期的起始日的标识符。

自定义日期和时间格式化器

日期和时间格式化器提供了一种便捷的方式从四种日期格式和四种时间格式进行挑选和组合。不过,如果您想要些不同的东西,您可以直接更改格式化器所使用的模式(或模板(template)。您想知道stock模式是什么样子吗?简单地使用getDateTimePattern()方法来获取它们。

然而,真正的兴奋在于setDateTimePattern()方法,它需要一个简单的文本字符串来描述输出应该是什么样子。在此重复参考手册没有什么意义,但是,在这里给出一个简单的例子:
//注意:下面的模式是本地化的(不是这些字母自身,
//而是使用它们表示格式化模式)!
const datePattern:String = "yyyy-MM-dd  (EEE)";  //模式是本地化的! dateFormatter.setDateTimePattern(datePattern); var now:Date = new Date(); var todayText:String = dateFormatter.format(now);

使用一个英语的区域,这个例子将输出这样的东西:“2009-08-17 (Mon)”。但是,请注意,确切的结果可能会因操作系统而略有不同。

如果您的应用提供了一种方法来让用户设置其个人偏好,那么您现在可以为long和short日期或时间格式创造不同的设置,让每个用户按照他或她想象的内容进行修改。

如果您是打算在应用程序的代码中定制模式,请记住,除非您有特殊的需要,那么格式模式很可能是可本地化的(也就是说,为了适应不同地区的用户,它们可能要被改变) 。因此,您必须对它们外部化,就如在用户界面中所使用的文本字符串那样,这样您的翻译人员就可以根据需要加以调整了。而且,在所有情况下,明智的做法是向用户提供覆盖您的选择的方式。

尽可能地,只是坚持用DateTimeFormatter类提供的stock格式:毕竟,它的存在就是为了在匆忙的工作中进行自动地选择正确的适应(adaptation)。

上一页(Par6) / 下一页(Par8)

riadevID: 
您给予的分值: None

发表新评论

  • 网页地址和电子邮件地址将会被自动转换为链接。
  • 行和段被自动切分。
  • 您可以使用下面的标签来高亮显示您的评论内容: <code>, <blockcode>. 可以使用"[foo]".旁边显示标签样式 "<foo>" PHP代码可以用这样的区块来包含<?php ... ?> or <% ... %>

更多格式化选项信息

验证区域
系统验证:请回答下面的问题