持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情
pub地址:pub.dev/packages/in…
Github地址:github.com/dart-lang/i…
主要使用的类是DateFormat、NumberFormat。
在使用任何格式化的方法之前,都应加载环境内容。
import 'package:intl/date_symbol_data_local.dart';
initializeDateFormatting();
为了统一演示结果,我们给一个默认的环境。
//设置默认的环境为英文
setState(
() {
//手动切换中文
S.load(const Locale("en"));
},
);
数字格式化
要格式化数字,需要先创建NumberFormat实例,并设置格式化样式。
比较常用的就是“#”和“0”,#表示可选的输出(不补零),0表示必须输出(没有则补零)。
在使用“#”和“0”的时候,要注意进位的问题,Intl使用的是银行家算法进位,特别是在一些位数要求比较严格的场合上,没控制好使用,可能造成很多不必要的麻烦。大家仔细看控制台输出的内容。
NumberFormat nf = NumberFormat("#,###.##");
print("1234567890.123 => #,###.## = ${nf.format(1234567890.123)}");
//?使用00就可以保留指定的小数位
nf = NumberFormat("#,###.00");
print("#,###.00 = ${nf.format(1234567890.09876)}");
nf = NumberFormat("#,###.000%");
print("#,###.000% = ${nf.format(0.09876)}");
nf = NumberFormat("%#,###.000");
print("%#,###.000 = ${nf.format(0.09876)}");
nf = NumberFormat("#,###.000‰");
print("#,###.000‰ = ${nf.format(0.09876)}");
//? 只能显示货币的名称,不能显示符号。
nf = NumberFormat("¤#,###.000");
print("¤#,###.000 = ${nf.format(09876)}");
nf = NumberFormat("¤#,###.000", "ZH");
print("¤#,###.000 = ${nf.format(09876)}");
输出内容
flutter: 1234567890.123 => #,###.## = 1,234,567,890.12
flutter: #,###.00 = 1,234,567,890.10
flutter: #,###.000% = 9.876%
flutter: %#,###.000 = %9.876
flutter: #,###.000‰ = 98.760‰
flutter: ¤#,###.000 = USD9,876.000
flutter: ¤#,###.000 = CNY9,876.000
目前已知的限制是:
1、货币格式只会印上货币名称,而不支持货币符号.
2、科学格式并不真正符合科学记数法。
3、数字解析尚未实现。
进位采用的是银行家舍入法
print("===============进位使用银行家舍入法================");
//! 银行家舍入法进位
//!四舍六入,五考虑,五后有值进位,五后没值看前位,奇数舍去,偶数进位。
nf = NumberFormat("#.#");
print("1.14,四舍${nf.format(1.14)}");
print("1.16,六入${nf.format(1.16)}");
print("1.151,五后有值进位)${nf.format(1.151)}");
print("1.15,五后没值看前位,奇数舍去${nf.format(1.15)}");
print("1.25,五后没值看前位,偶数进位${nf.format(1.25)}");
输出内容
flutter: ===============进位使用银行家算法================
flutter: 1.14,四舍1.1
flutter: 1.16,六入1.2
flutter: 1.151,五后有值进位)1.2
flutter: 1.15,五后没值看前位,奇数舍去1.1
flutter: 1.25,五后没值看前位,偶数进位1.3
日期格式化
要格式化日期时间,先创建一个DateFormat实例。然后设置需要的格式化符号。
//打印当天的年份
print("当天年份(y):${DateFormat.y().format(now)}");
//控制台输出: 当天年份(y):2022
//打印当天的月份
print("当天月份(M):${DateFormat.M().format(now)}");
//控制台输出: 当天月份(M):6
//打印当天的日期
print("当天日期(d):${DateFormat.d().format(now)}");
//控制台输出: 当天日期(d):9
//打印当天的星期
print("当天星期(E):${DateFormat.E().format(now)}");
//控制台输出: 当天星期(E):Thu
//打印当天的时间
print("当天时间(Hms):${DateFormat.Hms().format(now)}");
//控制台输出: 当天时间(Hms):21:44:41
print("y():${DateFormat.y().format(now)}");
//控制台输出: y():2022
print("yM():${DateFormat.yM().format(now)}");
//控制台输出: yM():6/2022
print("YMEd():${DateFormat.yMEd().format(now)}");
//控制台输出: YMEd():Thu, 6/9/2022
print("yMMM():${DateFormat.yMMM().format(now)}");
//控制台输出: yMMM():Jun 2022
print("yMMMEd():${DateFormat.yMMMEd().format(now)}");
//控制台输出: yMMMEd():Thu, Jun 9, 2022
print("yMMMM():${DateFormat.yMMMM().format(now)}");
//控制台输出: yMMMM():June 2022
print("yMMMMEEEEd():${DateFormat.yMMMMEEEEd().format(now)}");
//控制台输出: yMMMMEEEEd():Thursday, June 9, 2022
print("yMMMMd():${DateFormat.yMMMMd().format(now)}");
//控制台输出: yMMMMd():June 9, 2022
print("yMd():${DateFormat.yMd().format(now)}");
//控制台输出: yMd():6/9/2022
print(DateFormat.jm().format(now));
//控制台输出: 9:44 PM
print(DateFormat.j().format(now));
//控制台输出: 9 PM
print(DateFormat.jms().format(now));
//控制台输出: 9:44:41 PM
print(DateFormat.Hm().format(now));
//控制台输出: 21:44
可以组合使用,例如
print("yM():${DateFormat.yM().add_Hm().format(now)}");
//控制台输出: yM():6/2022 21:44
当然是你还可以设置语言:
//打印当天的年份
print("当天年份(y):${DateFormat.y("zh").format(now)}");
//控制台输出: 当天年份(y):2022年
//打印当天的月份
print("当天月份(M):${DateFormat.M("zh").format(now)}");
//控制台输出: 当天月份(M):6月
//打印当天的日期
print("当天日期(d):${DateFormat.d("zh").format(now)}");
//控制台输出: 当天日期(d):9日
//打印当天的星期
print("当天星期(E):${DateFormat.E("zh").format(now)}");
//控制台输出: 当天星期(E):周四
//打印当天的时间
print("当天时间(Hms):${DateFormat.Hms("zh").format(now)}");
//控制台输出: 当天时间(Hms):21:44:41
print("y():${DateFormat.y("zh").format(now)}");
//控制台输出: y():2022年
print("yM():${DateFormat.yM("zh").format(now)}");
//控制台输出: yM():2022年6月
print("YMEd():${DateFormat.yMEd("zh").format(now)}");
//控制台输出: YMEd():2022/6/9周四
print("yMMM():${DateFormat.yMMM("zh").format(now)}");
//控制台输出: yMMM():2022年6月
print("yMMMEd():${DateFormat.yMMMEd("zh").format(now)}");
//控制台输出: yMMMEd():2022年6月9日周四
print("yMMMM():${DateFormat.yMMMM("zh").format(now)}");
//控制台输出: yMMMM():2022年6月
print("yMMMMEEEEd():${DateFormat.yMMMMEEEEd("zh").format(now)}");
//控制台输出: yMMMMEEEEd():2022年6月9日星期四
print("yMMMMd():${DateFormat.yMMMMd("zh").format(now)}");
//控制台输出: yMMMMd():2022年6月9日
print("yMd():${DateFormat.yMd("zh").format(now)}");
//控制台输出: yMd():2022/6/9
print(DateFormat.jm("zh").format(now));
//控制台输出: 下午9:44
print(DateFormat.j("zh").format(now));
//控制台输出: 下午9时
print(DateFormat.jms("zh").format(now));
//控制台输出: 下午9:44:41
print(DateFormat.Hm("zh").format(now));
//控制台输出: 21:44
print("yM():${DateFormat.yM("zh").add_Hm().format(now)}");
//控制台输出: yM():2022年6月 21:44
最后,展示我最喜欢的方式,应该是java代码写多了,我还是觉得这么写最舒服。
print("yyyy():${DateFormat("yyyy").format(now)}");
//控制台输出: yyyy():2022
print("yyyy-MM():${DateFormat("yyyy-MM").format(now)}");
//控制台输出: yyyy-MM():2022-06
print("yyyy-MM-dd():${DateFormat("yyyy-MM-dd").format(now)}");
//控制台输出: yyyy-MM-dd():2022-06-09
print(
"yyyy-MM-dd HH:mm:ss():${DateFormat("yyyy-MM-dd HH:mm:ss").format(now)}");
//控制台输出: yyyy-MM-dd HH:mm:ss():2022-06-09 21:44:41
print(DateFormat("一年中的第D天,一年中的第Q个季度").format(now));
//控制台输出: 一年中的第160天,一年中的第2个季度
我在使用时候发现,intl对日期的处理不符合我的要求,其实我期望的是一个数字的星期“1”,但是他就是不能给我输出这个数字“1”。还是要使用Dart的日期处理能力来解决,这个使用确实不舒服。
我理解是Intl对ICU中的“w”以及“W”符号还没有支持的原因吧,也许对这两个符号支持后就好了。
print("E:${DateFormat("E").format(now)}");
//控制台输出: E:Thu
print("E(zh):${DateFormat("E", "zh").format(now)}");
//控制台输出: E(zh):周四
print("DateTime.now().weekday:${DateTime.now().weekday}");
//控制台输出: DateTime.now().weekday:4
\
加载环境的3种方式
官方推荐在执行任何格式化方法之前,都需要加载一个本地环境。提供了3中加载的方式,个人觉得啊从本地环境加载最方便呢,剩下的两种扩展性会更好,但是这个国际化真的需要这么高的扩展性吗?可能做产品的和我这种写代码的想法不一样吧。
- 从本地环境中加载,这个方法最方便。在方法的定义上能看到local和ignored是可以为空的参数,实际上这里传任何值都没有意义,intl会忽律这两个参数,因为所有语言环境的数据都是直接可用的。
import 'package:intl/date_symbol_data_local.dart';
//方法的定义,local和ignored都可以为空,所以直接调用放就可以了,
//Future<void> initializeDateFormatting([String? locale, String? ignored])
initializeDateFormatting();
- 如果你自己有写好的环境文件,也可以是加载本地文件。
import 'package:intl/date_symbol_data_file.dart';
Future<void> initializeDateFormatting(String locale, String filePath)
- 最后一种是加载网络上的环境文件。
import 'package:intl/date_symbol_data_http_request.dart';
Future<void> initializeDateFormatting(String locale, String url)
已知限制:
1、时区尚不支持。Dart DateTime对象没有时区,因此是本地或UTC。
2、格式化和解析持续时间尚未实现。
\
附件内容:
数字格式化支持的符号
/// - `0` 一个位数,没有值用0补齐
/// - `#` 一个位数, 值为0时忽律。
/// - `.` 十进制分隔符
/// - `-` 减号
/// - `,` 分组符号
/// - `E` 将尾数和指数分开
/// - `+` - 在指数之前,要说它应该加上加号。
/// - `%` - 作为前缀或者后缀使用,数值会乘以100,变成百分数。
/// - `‰ (\u2030)` 作为前缀或者后缀使用,数值会乘以100,变成百分数。
/// - `¤ (\u00A4)` 货币符号,替换为货币名称
/// - `'` 用于引用特殊字符
/// - `;` 用于分离正反模式 (如果两者都存在)
银行家舍入法
日期格式化支持的符号-ICU格式列表
测试发现目前的Intl还没有实现全部的ICU/JDK符号,(这个链接是ICU所有的格式列表,有兴趣的了解一下。)下边这个表格,是目前Intl已经实现的ICU符号,够不够用的看大家的业务吧。
ICU Name Skeleton
-------- --------
DAY d
ABBR_WEEKDAY E
WEEKDAY EEEE
ABBR_STANDALONE_MONTH LLL
STANDALONE_MONTH LLLL
NUM_MONTH M
NUM_MONTH_DAY Md
NUM_MONTH_WEEKDAY_DAY MEd
ABBR_MONTH MMM
ABBR_MONTH_DAY MMMd
ABBR_MONTH_WEEKDAY_DAY MMMEd
MONTH MMMM
MONTH_DAY MMMMd
MONTH_WEEKDAY_DAY MMMMEEEEd
ABBR_QUARTER QQQ
QUARTER QQQQ
YEAR y
YEAR_NUM_MONTH yM
YEAR_NUM_MONTH_DAY yMd
YEAR_NUM_MONTH_WEEKDAY_DAY yMEd
YEAR_ABBR_MONTH yMMM
YEAR_ABBR_MONTH_DAY yMMMd
YEAR_ABBR_MONTH_WEEKDAY_DAY yMMMEd
YEAR_MONTH yMMMM
YEAR_MONTH_DAY yMMMMd
YEAR_MONTH_WEEKDAY_DAY yMMMMEEEEd
YEAR_ABBR_QUARTER yQQQ
YEAR_QUARTER yQQQQ
HOUR24 H
HOUR24_MINUTE Hm
HOUR24_MINUTE_SECOND Hms
HOUR j
HOUR_MINUTE jm
HOUR_MINUTE_SECOND jms
HOUR_MINUTE_GENERIC_TZ jmv (not yet implemented)
HOUR_MINUTE_TZ jmz (not yet implemented)
HOUR_GENERIC_TZ jv (not yet implemented)
HOUR_TZ jz (not yet implemented)
MINUTE m
MINUTE_SECOND ms
SECOND s