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

如何在Java中解析指定时间字符串并生成LocalDateTime?

问题描述

我有以下通过正则从上传数据中提取的时间字符串:

Wednesday, 30 Nov 2022 10:30:00 (UTC)
12/08 (Thu), 10:00 GMT

希望在Java中将这些字符串转换为LocalDateTime类型,期望生成的结果为:

2022/11/30 10:30:00 UTC
2022/12/08 10:00:00 GMT

我编写了对应的处理代码,但调试许久仍未得到预期结果,需要返回Java的LocalDateTime类型,寻求解决方法。

我的代码
@Override
public List<LocalDateTime> getTime(String str) {
  Matcher matcher = regex("(\\d+)\\/(\\d+)\\(\\W\\), \\d+:\\d+-(\\d+):(\\d+)\\s+(\\w+)", str);
  LocalDateTime date;
  List<LocalDateTime> list = new ArrayList<>();
  int year, month, day, hour, minute, second;
  ZoneId timezone;
  year = LocalDateTime.now().getYear();
  while(matcher.find()){
    month = getMonth(matcher.group(1));
    day = Integer.parseInt(matcher.group(2));
    hour = Integer.parseInt(matcher.group(3));
    minute = Integer.parseInt(matcher.group(4));
    second = 0;
    if(matcher.group(5).equals("KST")) {
      timezone = ZoneId.of("Asia/Seoul");
    }
    else{
      timezone = ZoneId.of(matcher.group(5));
    }
    date = LocalDateTime.of(year, month, day, hour, minute, second);

    ZonedDateTime time = ZonedDateTime.of(date, timezone);
    LocalDateTime result = timeZoneConverter(time);
    list.add(result);
  }
  return list;
}

public static Matcher regex(String regex, String input) {
  return Pattern.compile(regex, Pattern.MULTILINE).matcher(input);
}

public static int getMonth(String s) {
  int result = 0;
  switch (s) {
    case "1":
    case "Jan":
      result = 1;
    case "Feb":
    case "2":
      result = 2;
    case "Mar":
    case "3":
      result = 3;
    case "Apr":
    case "4":
      result = 4;
    case "May":
    case "5":
      result = 5;
    case "Jun":
    case "6":
      result = 6;
    case "Jul":
    case "7":
      result = 7;
    case "Aug":
    case "8":
      result = 8;
    case "Sep":
    case "9":
      result = 9;
    case "Oct":
    case "10":
      result = 10;
    case "Nov":
    case "11":
      result = 11;
    case "Dec":
    case "12":
      result = 12;
  }
  return result;
}

public static LocalDateTime timeZoneConverter(ZonedDateTime dateTime) {
  ZonedDateTime resultZonedDateTime = dateTime.withZoneSameInstant(ZoneId.of("Asia/Seoul"));

  LocalDateTime localDate = LocalDateTime.parse(resultZonedDateTime.toLocalDateTime().toString());
  System.out.println("localDate = " + localDate);
  return localDate;
}
问题分析与解决方法

你的代码存在几个核心问题:

  1. 正则完全不匹配目标格式:
    现有正则既没覆盖带英文月份、完整年份的第一种时间格式,还错误加入了不存在的-时间分隔符,导致两种格式都无法匹配。
  2. getMonth方法逻辑错误:
    switch分支未加break,匹配任意月份后都会执行到最后一个case,最终月份恒为12。
  3. 时区逻辑与需求不符:
    你期望保留原时区的时间,但timeZoneConverter强制转成了首尔时区,同时LocalDateTime本身不存储时区信息,若要保留时区需用ZonedDateTime配合单独存储时区标识。
  4. 手动解析易出错:
    手动拆分时间字段的方式繁琐且容易遗漏边界情况,Java自带的DateTimeFormatter能更可靠处理多格式时间解析。

修正后的代码

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

@Override
public List<LocalDateTime> getTime(String str) {
    List<LocalDateTime> resultList = new ArrayList<>();
    // 定义两种时间格式的解析器
    DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("EEEE, dd MMM yyyy HH:mm:ss (zzz)", Locale.ENGLISH);
    DateTimeFormatter formatter2 = new DateTimeFormatterBuilder()
            .appendPattern("MM/dd (EEE), HH:mm ")
            .appendZoneText()
            .parseDefaulting(ChronoField.YEAR, LocalDateTime.now().getYear())
            .toFormatter(Locale.ENGLISH);

    String[] timeStrings = str.split("\\n");
    for (String timeStr : timeStrings) {
        timeStr = timeStr.trim();
        if (timeStr.isEmpty()) continue;

        ZonedDateTime zonedDateTime;
        try {
            // 先尝试匹配第一种带完整年份的格式
            zonedDateTime = ZonedDateTime.parse(timeStr, formatter1);
        } catch (Exception e) {
            // 匹配失败则用第二种格式(自动补充当前年份)
            zonedDateTime = ZonedDateTime.parse(timeStr, formatter2);
        }

        // 将带时区的时间转为LocalDateTime(仅保留时间值,时区需单独存储)
        resultList.add(zonedDateTime.toLocalDateTime());

        // 如需输出期望格式的字符串,可使用以下代码
        DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss zzz", Locale.ENGLISH);
        System.out.println(zonedDateTime.format(outputFormatter));
    }
    return resultList;
}

代码说明

  • 用DateTimeFormatter分别适配两种时间格式,无需手动写正则拆分字段,避免解析错误。
  • 第二种格式无年份,通过parseDefaulting自动补充当前年份。
  • 先解析为ZonedDateTime保留时区信息,再按需转为LocalDateTime。
  • 可通过指定格式化器直接输出你期望的字符串格式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 19:30:32