parse 静态方法
- String formattedString
基于formattedString
构建一个新的DateTime实例。
如果输入字符串无法解析,将抛出FormatException异常。
该函数解析ISO 8601的子集,包括RFC 3339接受的子集。
当前接受的输入包括
- 日期:表示为两位到一个六位数的年份、两位数的月份和两位数的日期,可由
-
字符分隔。例如:"19700101","-0004-12-24","81030-04-01"。 - 一个可选的时间部分,时间部分与日期部分由
T
或空格分隔。时间部分是一个两位数的小时,然后是可选的两位数分钟值,然后是可选的两位数秒值,接着是可选的'.'或','后跟至少一个数字的秒分数。分钟和秒可能由':'与前面的部分分隔。例如:"12","12:30:24.124","12:30:24,124","123010.50"。 - 一个可选的时间-时区偏移部分,可能由空格与之前部分分隔。时区可以是'z'或'Z',或者是一个带有可选两位数分钟部分的带符号的两位数小时部分。符号必须是"+"或"-",不能省略。分钟可能由小时分隔。例如:"Z","-10","+01:30","+1130"。
这包括toString
和toIso8601String
的输出,它们将被解析回与原始相同的DateTime
对象。
结果始终为本地时间或UTC。如果指定了除UTC之外的其他时区偏移,则将时间转换为等效的UTC时间。
接受的字符串示例
"2012-02-27"
"2012-02-27 13:27:00"
"2012-02-27 13:27:00.123456789z"
"2012-02-27 13:27:00,123456789z"
"20120227 13:27:00"
"20120227T132700"
"20120227"
"+20120227"
"2012-02-27T14Z"
"2012-02-27T14+00:00"
"-123450101 00:00:00 Z"
:在-12345年。"2002-02-27T14:00:00-0500"
:与"2002-02-27T19:00:00Z"
相同
此方法接受超出范围的组件值,并将其解释为下一次更大的组件的溢出。例如,"2020-01-42"将解析为2020-02-11,因为在那个月内的最后有效日期是2020-01-31,所以42天被解释为那个月的31天加上下一个月的11天。
要检测和拒绝无效的组件值,请使用来自intl包的DateFormat.parseStrict。
实现
static DateTime parse(String formattedString) {
var re = _parseFormat;
Match? match = re.firstMatch(formattedString);
if (match != null) {
int parseIntOrZero(String? matched) {
if (matched == null) return 0;
return int.parse(matched);
}
// Parses fractional second digits of '.(\d+)' into the combined
// microseconds. We only use the first 6 digits because of DateTime
// precision of 999 milliseconds and 999 microseconds.
int parseMilliAndMicroseconds(String? matched) {
if (matched == null) return 0;
int length = matched.length;
assert(length >= 1);
int result = 0;
for (int i = 0; i < 6; i++) {
result *= 10;
if (i < matched.length) {
result += matched.codeUnitAt(i) ^ 0x30;
}
}
return result;
}
int years = int.parse(match[1]!);
int month = int.parse(match[2]!);
int day = int.parse(match[3]!);
int hour = parseIntOrZero(match[4]);
int minute = parseIntOrZero(match[5]);
int second = parseIntOrZero(match[6]);
int milliAndMicroseconds = parseMilliAndMicroseconds(match[7]);
int millisecond =
milliAndMicroseconds ~/ Duration.microsecondsPerMillisecond;
int microsecond = milliAndMicroseconds
.remainder(Duration.microsecondsPerMillisecond) as int;
bool isUtc = false;
if (match[8] != null) {
// timezone part
isUtc = true;
String? tzSign = match[9];
if (tzSign != null) {
// timezone other than 'Z' and 'z'.
int sign = (tzSign == '-') ? -1 : 1;
int hourDifference = int.parse(match[10]!);
int minuteDifference = parseIntOrZero(match[11]);
minuteDifference += 60 * hourDifference;
minute -= sign * minuteDifference;
}
}
int? value = _brokenDownDateToValue(years, month, day, hour, minute,
second, millisecond, microsecond, isUtc);
if (value == null) {
throw FormatException("Time out of range", formattedString);
}
return DateTime._withValue(value, isUtc: isUtc);
} else {
throw FormatException("Invalid date format", formattedString);
}
}