You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter护照MRZ两位年份日期格式转换问题求助

解决方案:Flutter中MRZ日期转换问题

问题根源分析

  1. intl插件报错原因:你直接用了错误的DateFormat格式(比如yyyyMMdd)解析6位MRZ日期(YYMMDD格式),yyyy要求4位年份,解析6位字符串时会因长度不匹配抛出Trying to read MM from 000423 at position 6错误。
  2. 自定义Dart代码失效原因:未区分出生日期与护照有效期的年份处理逻辑——出生日期是过去日期,有效期是未来日期,两者的世纪补全规则不同。

方案1:自定义Dart转换函数(推荐)

通过明确区分日期类型(生日/有效期),补全正确的世纪,避免转换错误:

String convertMRZDate(String mrzDate, {bool isBirthDate = true}) {
  // 校验MRZ日期格式
  if (mrzDate.length != 6) {
    throw ArgumentError('MRZ日期必须是6位字符串');
  }

  // 拆分MRZ日期:YY MM DD
  final yearStr = mrzDate.substring(0, 2);
  final monthStr = mrzDate.substring(2, 4);
  final dayStr = mrzDate.substring(4, 6);

  final int twoDigitYear = int.parse(yearStr);
  final currentYear = DateTime.now().year;
  final currentTwoDigitYear = currentYear % 100;

  int fullYear;
  if (isBirthDate) {
    // 出生日期:两位年份大于当前年份后两位,补19xx;否则补20xx
    fullYear = twoDigitYear > currentTwoDigitYear ? 1900 + twoDigitYear : 2000 + twoDigitYear;
  } else {
    // 有效期:两位年份小于等于当前年份后两位,补21xx;否则补20xx(适配未来有效期)
    fullYear = twoDigitYear <= currentTwoDigitYear ? 2100 + twoDigitYear : 2000 + twoDigitYear;
  }

  // 构造日期并格式化输出
  final date = DateTime(fullYear, int.parse(monthStr), int.parse(dayStr));
  return '${dayStr}-${monthStr}-${fullYear.toString().padLeft(4, '0')}';
}

使用示例

// 转换出生日期:000423 → 23-04-2000
print(convertMRZDate('000423', isBirthDate: true));

// 转换有效期:301231 → 31-12-2030
print(convertMRZDate('301231', isBirthDate: false));

方案2:intl插件正确用法

先按YYMMDD格式解析,再根据日期类型调整世纪:

import 'package:intl/intl.dart';

String convertMRZDateWithIntl(String mrzDate, {bool isBirthDate = true}) {
  if (mrzDate.length != 6) {
    throw ArgumentError('MRZ日期必须是6位字符串');
  }

  // 按YYMMDD格式解析MRZ日期
  final mrzFormat = DateFormat('yyMMdd');
  DateTime date = mrzFormat.parse(mrzDate);

  final currentYear = DateTime.now().year;
  // 调整世纪:生日取过去的世纪,有效期取未来的世纪
  if (isBirthDate && date.year > currentYear) {
    date = date.subtract(const Duration(days: 36524)); // 减去约100年
  } else if (!isBirthDate && date.year < currentYear) {
    date = date.add(const Duration(days: 36524)); // 加上约100年
  }

  // 格式化为dd-MM-yyyy
  final outputFormat = DateFormat('dd-MM-yyyy');
  return outputFormat.format(date);
}

内容的提问来源于stack exchange,提问作者abhi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 15:17:40