SimpleDateFormat("EEEE") 返回错误的时区星期几

问题描述

我有以下简单代码可以根据时区获取星期几。

Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone(details.getTimezone()));
String dayOfWeek = new SimpleDateFormat("EEEE").format(calendar.get(Calendar.DAY_OF_WEEK));

此处,details.getTimezone() 返回可接受的值,例如“Asia/Kolkata”,而 calendar.get(Calendar.DAY_OF_WEEK) 返回正确的值 6。

按照顺序,第 6 天应该返回 "Friday",但该函数返回的是 "Thursday"

如果我做错了什么,请告诉我。

如果我对 DAY_OF_WEEK = 6 表示星期五的理解正确,请告诉我。

解决方法

java.time

java.util 日期时间 API 及其格式化 API SimpleDateFormat 已过时且容易出错。建议完全停止使用它们并切换到 modern Date-Time API*

使用现代 API java.time 的解决方案:

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

public class Main {
    public static void main(String[] args) {
        ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("Asia/Kolkata"));
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEEE",Locale.ENGLISH);
        System.out.println(dtf.format(zdt));
    }
}

输出:

Friday

modern Date-Time API 中详细了解 java.timeTrail: Date Time*

使用旧 API:

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

public class Main {
    public static void main(String[] args) {
        Date date = new Date();
        DateFormat sdf = new SimpleDateFormat("EEEE",Locale.ENGLISH);
        sdf.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));
        System.out.println(sdf.format(date));
    }
}

输出:

Friday

* 出于任何原因,如果您必须坚持使用 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

,
SimpleDateFormat s = new SimpleDateFormat("EEEE");

Date  date= new Date();

String dayOfTheWeek = s.format(date);

使用此代码获取周五结果

,

您的代码出了什么问题?

Java 1.0 和 1.1 中的旧日期和时间类设计糟糕且混乱,并且已经过时。

如果我做错了什么,请告诉我。

您做错的主要原因是您使用了错误的类。使用 java.time,现代 Java 日期和时间 API,如 Arvind Kumar Avinash 回答的前半部分所述。

关于 SimpleDateFormat 的一个令人困惑的事情是它接受将自纪元(UTC 时间开始时 1970-01-01)以来的毫秒数格式化为日期。您是正确的 calendar.get(Calendar.DAY_OF_WEEK) 今天返回 6,您正确的是这应该是星期五。 Calendar 表示从星期日开始的一周中的天数 = 1。当您将 6 传递给 SimpleDateFormat.format() 时,它会将 6 解释为 UTC 1970 年 1 月 1 日午夜过后 6 毫秒。1970 年 1 月 1 日是星期四(UTC 时间午夜过后 6 毫秒仍然是地球西半部的星期三)。由于在您所在的时区也是星期四,因此这是您获得的星期几。

所以可能重复我自己,不要使用那些旧类。使用 java.time。与它合作要好得多,而且要犯类似的错误要困难得多。

链接

Oracle tutorial: Date Time 解释如何使用 java.time。