怎么把这个字符串“ Mon Jan 01 00:00:00 AEDT 1990”转换成“ 1990101”?

时间:2019-05-30 01:20:39

标签: java regex string date parsing

我有一个字符串“ Mon Jan 01 00:00:00 AEDT 1990”,我需要将其转换为“ yyyyMMdd”格式,因此在这种情况下应为“ 19900101”。

我认为可以使用正则表达式来做到这一点,这样我就可以从字符串中提取年份,月份(但需要将Jan转换为01等)和日期,但是我并不精通正则表达式。有人有什么想法吗?

3 个答案:

答案 0 :(得分:6)

tl; dr

Regex太过分了。

这里是使用Java中内置的 java.time 类的单线解决方案。

ZonedDateTime                            // Represent a moment as seen through the wall-clock time used by the people of a certain region (a time zone).
.parse(                                  // Parse the input text.
    "Mon Jan 01 00:00:00 AEDT 1990" ,     
    DateTimeFormatter.ofPattern( 
        "EEE MMM dd HH:mm:ss z uuuu" ,   // Specify a custom formatting pattern to match our input.
        Locale.US                        // Specify a `Locale` for the human language to use in translating the name of month& day-of-week.
    )                                    // Returns a `DateTimeFormatter` object.
)                                        // Returns a `ZonedDateTime` object.
.toLocalDate()                           // Extract the date, without time-of-day and without time zone. 
.format(                                 // Generate text to represent the value of our `LocalDate` object.
    DateTimeFormatter.BASIC_ISO_DATE     // Use the predefined formatting pattern YYYYMMDD.
)                                        // Returns a String.
  

19900101

java.time

正则表达式对此过于矫

现代方法使用 java.time 类。

指定自定义格式设置模式以适合您的输入。

指定语言环境以方便翻译星期几的名称和月份的名称。

ZonedDateTime

解析为ZonedDateTime,即特定区域(时区)的人们使用的挂钟时间所看到的时刻。

String input = "Mon Jan 01 00:00:00 AEDT 1990";
Locale locale = Locale.US;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "EEE MMM dd HH:mm:ss z uuuu" , locale );
ZonedDateTime zdt = ZonedDateTime.parse( input , f );

System.out.println( "zdt: " + zdt );
  

zdt:1990-01-01T00:00 + 11:00 [澳大利亚/悉尼]

顺便说一句,您输入的字符串格式为可怕的。它使用2-4个字符的伪时区,它们不是实际的时区,不是标准化的,也不是唯一的!另一个问题取决于英语。而且很难解析。教育人们发布有关ISO 8601标准之美的数据,该标准是为交换日期时间值作为文本而创建的。

LocalDate

您只想要日期。因此,提取一个LocalDate

LocalDate ld = zdt.toLocalDate() ;  // Extract only the date, leaving behind the time-of-day and the time zone.

您所需的输出格式已在DateTimeFormatter类中定义。日期的标准ISO 8601格式为YYYY-MM-DD。的一种变体称为“基本”,表示它最大程度地减少了分隔符YYYYMMDD的使用。

String output = ld.format( DateTimeFormatter.BASIC_ISO_DATE ) ;
  

19900101

答案 1 :(得分:2)

检查这样是否有帮助

//date string
String soTime = "Mon Jan 04 12:30:23 AEDT 1990";

//Format
SimpleDateFormat so = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy");

SimpleDateFormat desiredFormat = new SimpleDateFormat("yyyyMMdd");
desiredFormat.setTimeZone(TimeZone.getTimeZone("Australia/Sydney"));

Date sodate = so.parse(soTime);
System.out.println("DAY : " + desiredFormat.format(sodate));

Parse date with AEDT and AEST time zone in java

答案 2 :(得分:1)

现在假设每个传递的字符串中的每个月和日名称与枚举name值之一匹配(即“ Mar” 与{中的字段name匹配) {1}},而“ Marc” “ March” 则不同),并且您提供给我们的示例字符串的格式是真正一致的,因为它不是主题要在运行时进行更改,并且将始终保持Month.MARCH,其中year始终是4位数字,以下代码应给出确切的答案:

主班

<day-name> <month> <day> <time> <zone> <year>

CustomDateFormat类

public static void main(String[] args) {

    String time = "Mon Jul 05 00:00:00 AEDT 1990";
    int result = CustomDateFormat.parseToInt(time);
    System.out.println("Parsed in format [yyyyMMdd]: " + result);
}

输出

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CustomDateFormat {

    private static final Pattern STANDARD_PATTERN =
    Pattern.compile("^(?:[a-zA-Z]{3})\\s([a-zA-Z]{3})\\s([0-9]{2}).*([0-9]{4})");

    /*
     * This is just in case you want
     * the name of the day as well
     */
    public enum Day {

        MONDAY("Mon", "Monday"),
        TUESDAY("Tue", "Tuesday"),
        WEDNESDAY("Wed", "Wednesday"),
        THURSDAY("Thu", "Thursday"),
        FRIDAY("Fri", "Friday"),
        SATURDAY("Sat", "Saturday"),
        SUNDAY("Sun", "Sunday");

        final String shortName;
        final String fullName;

        Day(String name1, String name2) {
            this.shortName = name1;
            this.fullName = name2;
        }

        public static String getFullName(String alias) {
            for (Day d : Day.values()) {
                if (d.shortName.equals(alias))
                    return d.fullName;
            }
            return "";
        }
    }

    public enum Month {

        JANUARY("Jan", 1), FEBRUARY("Feb", 2),
        MARCH("Mar", 3), APRIL("Apr", 4),
        MAY("May", 5), JUNE("Jun", 6),
        JULY("Jul", 7), AUGUST("Aug", 8),
        SEPTEMBER("Sep", 9), OCTOBER("Oct", 10),
        NOVEMBER("Nov", 11), DECEMBER("Dec", 12);

        final String name;
        final int value;

        Month(String name, int value) {
            this.name = name;
            this.value = value;
        }

        public static int getMonth(String month) {
            for (Month m : Month.values()) {
                if (m.name.equals(month))
                    return m.value;
            }
            return 0;
        }
    }

    public static int parseToInt(String date) {

        System.out.println("Parsing date: " + date);
        Matcher matcher = STANDARD_PATTERN.matcher(date);

        if (matcher.find() && matcher.groupCount() == 3)
        {
            int month = Month.getMonth(matcher.group(1));
            int day = Integer.valueOf(matcher.group(2));
            int year = Integer.valueOf(matcher.group(3));

            if (day == 0 || month == 0) {
                throw new IllegalStateException("Unable to parse day or month from date " + date);
            }
            else return Integer.valueOf(year + "0" + month + "0" + day);
        }
        else throw new IllegalStateException("Unable to parse date " + date);
    }
}

让我知道这是否满足您的要求,是否需要满足任何其他条件,或者是否考虑了特殊情况。这是一个非常简单的实现,因此无需花费任何时间即可将其调整为更具体的需求。

编辑:修正一些实现错误,将示例字符串更改为自定义字符串,并删除多余的输出行。