输入日期1月03日但是返回1月02日,为什么?

时间:2012-03-27 11:08:43

标签: java date

public static void main(String[] args) {
    String opDate = "Tue Jan 03 00:00:00 MSK 2006";
    String date = convertDate(opDate, "yyyyMMdd");

    System.out.println("opDate: " + opDate);
    System.out.println("date: " + date);
}

public static String convertDate(String opDate, String dateFormat) {
    Date date = new Date();
                                                    //  Mon Jan 02 00:00:00 MSK 2006
    SimpleDateFormat dateParser = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US);

    try {
        date = dateParser.parse(opDate);
    } catch (Exception e) {
        System.out.println("exception = " + e.toString());
    }

    SimpleDateFormat df = new SimpleDateFormat(dateFormat);
    df.setTimeZone(TimeZone.getTimeZone("Russia/Moscow"));
    String strDate = df.format( date.getTime() );

    return strDate.trim();
}

出:

  

opDate:Tue Jan 03 00:00:00 MSK 2006

     

日期:20060102

为什么会在1月02日返回?

6 个答案:

答案 0 :(得分:8)

问题是获取"Russia/Moscow"时区。正确的zoneinfo ID为"Europe/Moscow"。更改ID,问题消失了:

df.setTimeZone(TimeZone.getTimeZone("Europe/Moscow"));

遗憾的是,TimeZone.getTimeZone("random rubbish")返回UTC时区,而不是以某种方式告诉您它已被破坏。

答案 1 :(得分:5)

可能由于时区转换。 我建议你也打印结果日期的时间和时区。这可能是1月2日,23:00或其他什么。

这是因为您在SimpleDataFormat上设置了不同的时区。

答案 2 :(得分:3)

时区。

您指定1月3日午夜在MSK中。这是格林尼治标准时间1月2日晚上9点(可能的默认时区)。

我可以看到您在莫斯科时间也尝试输出,但Russia/Moscow不是有效的时区,getTimeZone来电"有帮助" silently defaults to returning GMT。这当然不会在格式化时更改日期的时区,并将其输出为1月2日。

如果您将时区设置为Europe/Moscow,您将获得预期的输出。

答案 3 :(得分:2)

是否与您在两个不同的时区之间转换日期有关?

答案 4 :(得分:1)

如果你换行:

String date = convertDate(opDate, "yyyyMMdd");

为:

String date = convertDate(opDate, "EEE MMM dd HH:mm:ss zzz yyyy");

你可以看到程序的输出:

opDate: Tue Jan 03 00:00:00 MSK 2006
date: Mon Jan 02 20:00:00 GMT 2006

你的TimeZone设置不好:

df.setTimeZone(TimeZone.getTimeZone("Russia/Moscow"));

你需要:

df.setTimeZone(TimeZone.getTimeZone("Europe/Moscow"));

最后夏天延迟1小时。

答案 5 :(得分:1)

java.time

time_resource_id, time_date t1 , t2 , t3 ------------------------------------------------------------------- 123 2021-06-19 8:00 10:00 13:00 日期时间 API 及其格式化 API java.util 已过时且容易出错。建议完全停止使用它们并切换到 modern Date-Time API*

使用 SimpleDateFormat(现代日期时间 API)的解决方案:

java.time

输出:

import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        String strDateTime = "Tue Jan 03 00:00:00 MSK 2006";
        String formatted = formatDateTimeStringTo(strDateTime, "yyyyMMdd", Locale.ENGLISH);

        System.out.println("opDate: " + strDateTime);
        System.out.println("date: " + formatted);
    }

    public static String formatDateTimeStringTo(String strDateTime, String targetFormat, Locale locale) {
        DateTimeFormatter parser = DateTimeFormatter.ofPattern("EEE MMM d H:m:s zzz u", locale);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(targetFormat, locale);
        ZonedDateTime zdt = ZonedDateTime.parse(strDateTime, parser);
        // System.out.println(zdt); // 2006-01-03T00:00+03:00[Europe/Moscow]
        return zdt.format(formatter);
    }
}

ONLINE DEMO

Trail: Date Time 了解有关现代 Date-Time API 的更多信息。

按照标准约定命名时区:

请您的发布商切换到时区的标准命名约定。 standard naming convention 是地区/城市,例如欧洲/莫斯科。时区的二/三/四字母缩写容易出错,如 Timezone documentation 页面中的以下文本所述:

<块引用>

三个字母的时区 ID

为了与 JDK 1.1.x 兼容,其他一些三字母时区 还支持 ID(例如“PST”、“CTT”、“AST”)。然而,他们的 不推荐使用因为相同的缩写经常用于 多个时区(例如,“CST”可以是美国的“Central 标准时间”和“中国标准时间”),Java平台可以 然后只识别其中一个。


* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 & 7. 如果您正在为 Android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project