chinese_date_utils.dart 5.13 KB
import 'package:intl/intl.dart';

class ChineseDateUtils {
  // 提取文本中所有日期
  static List<DateTime> extractAllDates(String text) {
    List<DateTime> dates = [];
    
    // 匹配中文日期
    dates.addAll(_extractChineseDates(text));
    
    // 匹配数字日期
    dates.addAll(_extractNumericDates(text));
    
    // 去重
    return dates.toSet().toList();
  }
  
  // 提取第一个找到的日期
  static DateTime? extractFirstDate(String text) {
    final dates = extractAllDates(text);
    return dates.isNotEmpty ? dates.first : null;
  }
  
  // 提取中文日期
  static List<DateTime> _extractChineseDates(String text) {
    List<DateTime> dates = [];
    
    // 支持多种格式
    final patterns = [
      RegExp(r'([正元一二三四五六七八九十腊]{1,2})月([一二三四五六七八九十]{1,3})[日号]'),
      RegExp(r'([正元一二三四五六七八九十腊]{1,2})月([初廿卅一二三四五六七八九十]{1,3})'),
    ];
    
    for (var pattern in patterns) {
      final matches = pattern.allMatches(text);
      
      for (var match in matches) {
        final date = _parseChineseDateMatch(match);
        if (date != null) {
          dates.add(date);
        }
      }
    }
    
    return dates;
  }
  
  // 提取数字日期
  static List<DateTime> _extractNumericDates(String text) {
    List<DateTime> dates = [];
    
    final patterns = [
      RegExp(r'(\d{1,2})[月\-/](\d{1,2})[日号]?'),
      RegExp(r'(\d{4})年(\d{1,2})月(\d{1,2})日'),
    ];
    
    for (var pattern in patterns) {
      final matches = pattern.allMatches(text);
      
      for (var match in matches) {
        DateTime? date;
        
        if (match.groupCount == 2) {
          // 月日格式
          int? month = int.tryParse(match.group(1)!);
          int? day = int.tryParse(match.group(2)!);
          
          if (month != null && day != null) {
            date = _createDate(month, day);
          }
        } else if (match.groupCount == 3) {
          // 年月日格式
          int? year = int.tryParse(match.group(1)!);
          int? month = int.tryParse(match.group(2)!);
          int? day = int.tryParse(match.group(3)!);
          
          if (year != null && month != null && day != null) {
            date = DateTime(year, month, day);
          }
        }
        
        if (date != null) {
          dates.add(date);
        }
      }
    }
    
    return dates;
  }
  
  static DateTime? _parseChineseDateMatch(Match match) {
    final monthStr = match.group(1);
    final dayStr = match.group(2);
    
    if (monthStr == null || dayStr == null) return null;
    
    final month = _chineseToMonth(monthStr);
    final day = _chineseToDay(dayStr);
    
    if (month == null || day == null) return null;
    
    return _createDate(month, day);
  }
  
  static int? _chineseToMonth(String chinese) {
    final Map<String, int> map = {
      '正': 1, '元': 1, '一': 1, '二': 2, '三': 3, '四': 4,
      '五': 5, '六': 6, '七': 7, '八': 8, '九': 9, '十': 10,
      '十一': 11, '腊': 12, '十二': 12
    };
    
    return map[chinese];
  }
  
  static int? _chineseToDay(String chinese) {
    // 处理农历日期前缀
    if (chinese.startsWith('初')) {
      return parseChineseNumber(chinese.substring(1));
    } else if (chinese.startsWith('廿')) {
      final rest = chinese.substring(1);
      return 20 + (parseChineseNumber(rest) ?? 0);
    } else if (chinese.startsWith('卅')) {
      final rest = chinese.substring(1);
      return 30 + (parseChineseNumber(rest) ?? 0);
    }
    
    return parseChineseNumber(chinese);
  }
  
  static int? parseChineseNumber(String chinese) {
    if (chinese.isEmpty) return null;
    
    final Map<String, int> singleDigits = {
      '一': 1, '二': 2, '三': 3, '四': 4, '五': 5,
      '六': 6, '七': 7, '八': 8, '九': 9, '十': 10
    };
    
    // 处理简单数字
    if (singleDigits.containsKey(chinese)) {
      return singleDigits[chinese];
    }
    
    // 处理组合数字
    if (chinese.contains('十')) {
      final parts = chinese.split('十');
      
      if (parts.length == 2) {
        int? tens = parts[0].isEmpty ? 1 : singleDigits[parts[0]];
        int? ones = parts[1].isEmpty ? 0 : singleDigits[parts[1]];
        
        if (tens != null && ones != null) {
          return tens * 10 + ones;
        }
      }
    }
    
    return null;
  }
  
  static DateTime? _createDate(int month, int day) {
    try {
      final now = DateTime.now();
      final year = now.year;
      
      // 验证日期有效性
      final lastDay = DateTime(year, month + 1, 0).day;
      if (day < 1 || day > lastDay) return null;
      
      return DateTime(year, month, day);
    } catch (e) {
      return null;
    }
  }
  
  // 格式化日期输出
  static String formatDate(DateTime date, {String format = 'yyyy年MM月dd日'}) {
    return DateFormat(format).format(date);
  }
  
  // 判断是否为有效日期
  static bool isValidDate(int year, int month, int day) {
    if (month < 1 || month > 12) return false;
    if (day < 1) return false;
    
    final lastDay = DateTime(year, month + 1, 0).day;
    return day <= lastDay;
  }
}