简体   繁体   English

Java日历每周星期几不正确

[英]Java Calendar doesn't get correct day of the week

I am currently working on app which needs to works with dates, hours and such. 我目前正在开发需要与日期,时间等配合使用的应用程序。 I got stuck on a pretty simple problem: getting the right day of the week from a given date (in milliseconds). 我遇到了一个非常简单的问题:从给定日期(以毫秒为单位)获取一周中的正确日期。 I know for sure that the given time in milliseconds for the current date is the right one, the problem is with the date the _calendar variable returns is one day after the one given. 肯定知道当前日期的给定时间(以毫秒为单位)是正确的,问题在于_calendar变量返回的日期是给定时间的一天之后。

I've tried using DateFormat or other date processing classes from Java, but my current min API for the android app is 22. 我尝试使用DateFormat或Java的其他日期处理类,但是当前用于android应用的最小API是22。

private void getDayOfTheWeek(Long dateInMillis) {
    Date _date = new Date();
    _date.setTime(dateInMillis);
    Calendar _calendar = Calendar.getInstance();
    _calendar.setTime(_date);
    mDayOfTheWeek = mDaysOfTheWeek[_calendar.get(Calendar.DAY_OF_WEEK) - 1];
    Log.d("FirebaseDay", mDayOfTheWeek + "; " + _calendar.getTimeInMillis());
}

For example, for the date: 1564088400000 It should return: 5, which is Friday, although the logged value for _calendar.getTimeInMillis() is the same as the given one 例如对于日期: 1564088400000它应返回:5,即星期五,尽管_calendar.getTimeInMillis()的记录值与给定的值相同

Edit: The problem is not that it returns a number, I have an array of strings, mDaysOfTheWeek which gets me the day after the integer received from _calendar . 编辑:问题不在于它返回一个数字,我有一个字符串数组mDaysOfTheWeek ,它使我从_calendar接收到整数后的_calendar 6 is the result given back. 结果为6。

private final String[] mDaysOfTheWeek
        = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}; 

tl;dr tl; dr

It should return: 5, which is Friday, … 6 is the result given back. 它应该返回:5,即星期五,…6是返回的结果。

The terrible Calendar class has many problems. 糟糕的Calendar类有很多问题。

  • One problem is its use of shifting behavior implicitly depending on the JVM's current default locale. 一个问题是它根据JVM当前的默认语言环境隐式使用了转换行为。 When your code runs on a JVM set to United States locale, you will find Thursday to be a different day of the week of Sunday-Saturday, than in Europe or other places where a week is Monday-Sunday. 当您的代码在设置为美国区域设置的JVM上运行时,您会发现星期四是星期日至星期六的一周中的另一天,而不是欧洲或一周中星期一至星期日的其他地方。
  • Another problem is crazy zero-based counting, 0-6 for days of the week, and 0-11 for months. 另一个问题是疯狂的从零开始的计数,一周中的几天为0-6,几个月为0-11。

Use java.time instead. 使用java.time代替。 The counting is sane (1-7 for Monday-Sunday), and the time zone behavior can be made predictable and explicit. 计数是合理的(周一至周日为1-7),并且可以使时区行为可预测和明确。

Important: Time zone is crucial. 重要提示:时区至关重要。 For more eastern zones, your moment appears as Friday. 对于更东部的地区,您的时刻显示为星期五。 For more western zones, your moment appears as Thursday. 对于其他西部地区,您的时刻显示为星期四。

Instant                            // Represent a moment in UTC.
.ofEpochMilli(                     // Parse your count-from-epoch 1970-01-01T00:00:00Z.
    1_564_088_400_000L             // Use underscores where you like, to make numeric literals more readable.
)                                  // Returns an `Instant` object.
.atZone(                           // Adjust from UTC to some time zone.
    ZoneId.of( "Asia/Tokyo" )      // Specify time zone using `Continent/Region` format, never 2-4 letter pseudo-zones such as `EST` or `CST` or `IST`. 
)                                  // Returns a `ZonedDateTime` object.
.getDayOfWeek()                    // Returns a `DayOfWeek` object.
.getDisplayName(                   // Generate automatically-localized string for the name of the day-of-week.
    TextStyle.FULL ,               // How long or abbreviated.
    Locale.US                      // Locale determines (a) human language for translation, and (b) cultural norms for issues such as abbreviation, punctuation, capitalization.
)                                  // Returns a `String`.

See this code run live at IdeOne.com . 看到此代码在IdeOne.com上实时运行

Friday 星期五

If you insist on a number 1-7 for Monday-Sunday, call getValue instead of .getDisplayName . 如果您坚持周一至周日为1-7,请致电getValue而不是.getDisplayName

.getValue()

5 5

Avoid legacy date-time classes 避免使用旧的日期时间类

I am currently working on app which needs to works with dates, hours and such. 我目前正在开发需要与日期,时间等配合使用的应用程序。

Then you should stop using the terrible date-time classes that were obsoleted years ago by the adoption of JSR 310. Use only the modern java.time classes. 然后,您应该停止使用几年前通过JSR 310淘汰的可怕的日期时间类。仅使用现代的java.time类。 Never use Date or Calendar . 切勿使用DateCalendar

Count-from-epoch 从时代开始计数

from a given date (in milliseconds). 从给定日期(以毫秒为单位)开始。

If you mean a count of milliseconds since the epoch reference of first moment of 1970 in UTC, then parse as an Instant . 如果您指的是自UTC 1970年第一时刻的纪元参考以来的毫秒数,请解析为Instant An Instant represents a moment in UTC, a specific point on the timeline. Instant表示UTC中的时刻,即时间轴上的特定点。

Instant instant = Instant.ofEpochMilli( 1_564_088_400_000L ) ;

See this code run live at IdeOne.com. 看到此代码在IdeOne.com上实时运行。

instant.toString(): 2019-07-25T21:00:00Z Instant.toString():2019-07-25T21:00:00Z

Date 日期

getting the right day of the week 得到正确的一周中的一天

Determining a date from a moment requires the context of a time zone. 从瞬间确定日期需要时区的上下文。 For any given moment the date varies around the globe by zone. 在任何给定的时刻,日期都会在全球范围内变化。 The date can simultaneously be “tomorrow” in Paris France while “yesterday” in Montréal Québec. 日期可以同时在法国巴黎的“明天”,而在蒙特利尔魁北克的“昨天”。

Specify a proper time zone name in the format of Continent/Region , such as America/Montreal , Africa/Casablanca , or Pacific/Auckland . Continent/Region的格式指定正确的时区名称 ,例如America/MontrealAfrica/CasablancaPacific/Auckland Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!). 切勿使用2-4字母的缩写,例如ESTIST因为它们不是真实的时区,不是标准化的,甚至不是唯一的(!)。

ZoneId z = ZoneId.of( "America/Montreal" ) ;  
LocalDate today = LocalDate.now( z ) ;

To adjust a moment into a time zone, apply a ZoneId to your Instant to get a ZonedDateTime . 要将时刻调整为时区, ZoneId应用于Instant以获得ZonedDateTime

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;

If you want to view the date through the lens of UTC rather than some other time zone, use OffsetDateTime class. 如果要通过UTC而不是其他时区查看日期,请使用OffsetDateTime类。

ZoneOffset offset = ZoneOffset.UTC ;  // Constant for UTC (an offset of zero hours-minutes-seconds). 
OffsetDateTime odt = instant.atOffset( offset ) ;

If you want to go this route (UTC), replace zdt in code below with this odt . 如果您想走这条路线(UTC),请将下面代码中的zdt替换为此odt

Day of week 星期几

Interrogate for the day-of-week using the DayOfWeek enum. 使用DayOfWeek枚举查询一周中的某天。

DayOfWeek dow = zdt.getDayOfWeek() ;

or example, for the date: 1564088400000 It should return: 5, 例如:日期:1564088400000,应返回:5

No, I suggest you work with smart objects rather than dumb integers. 不,我建议您使用智能对象,而不要使用哑整数。 Rather than using 5 to mean Friday (which, by the way, would mean Thursday in the United States), pass DayOfWeek enum objects around your code base. 而不是使用5表示Friday (顺便说一句,在美国将表示Thursday ),而是在代码库中传递DayOfWeek枚举对象。

To report the day-of-week to use, localize. 要报告要使用的星期几,请进行本地化。

String output = dow.getDisplayName( TextStyle.FULL , Locale.CANADA_FRENCH ) ;

Or, if you insist, generate a number using the ISO 8601 numbering scheme of 1-7 for Monday-Sunday. 或者,如果您坚持要使用星期一到星期日的1-7的ISO 8601编号方案生成一个数字。

int dayOfWeekNumber = dow.getValue() ; 

private final String[] mDaysOfTheWeek = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}; 私有最终String [] mDaysOfTheWeek = {“星期一”,“星期二”,“星期三”,“星期四”,“星期五”,“星期六”,“星期日”};

No need to roll-your-own. 无需自己动手。 Use the DayOfWeek enum. 使用DayOfWeek枚举。


About java.time 关于java.time

The java.time framework is built into Java 8 and later. java.time框架内置于Java 8及更高版本中。 These classes supplant the troublesome old legacy date-time classes such as java.util.Date , Calendar , & SimpleDateFormat . 这些类取代了麻烦的旧的旧式日期时间类,例如java.util.DateCalendarSimpleDateFormat

To learn more, see the Oracle Tutorial . 要了解更多信息,请参见Oracle教程 And search Stack Overflow for many examples and explanations. 并在Stack Overflow中搜索许多示例和说明。 Specification is JSR 310 . 规格为JSR 310

The Joda-Time project, now in maintenance mode , advises migration to the java.time classes. 现在处于维护模式Joda-Time项目建议迁移到java.time类。

You may exchange java.time objects directly with your database. 您可以直接与数据库交换java.time对象。 Use a JDBC driver compliant with JDBC 4.2 or later. 使用与JDBC 4.2或更高版本兼容的JDBC驱动程序 No need for strings, no need for java.sql.* classes. 不需要字符串,不需要java.sql.*类。

Where to obtain the java.time classes? 在哪里获取java.time类?

The ThreeTen-Extra project extends java.time with additional classes. ThreeTen-Extra项目使用其他类扩展了java.time。 This project is a proving ground for possible future additions to java.time. 该项目为将来可能在java.time中添加内容提供了一个试验场。 You may find some useful classes here such as Interval , YearWeek , YearQuarter , and more . 您可以在这里找到一些有用的类,比如IntervalYearWeekYearQuarter ,和更多

If you look at to Calendar class 如果看Calendar

/**
 * Value of the {@link #DAY_OF_WEEK} field indicating
 * Sunday.
 */
public final static int SUNDAY = 1;

/**
 * Value of the {@link #DAY_OF_WEEK} field indicating
 * Monday.
 */
public final static int MONDAY = 2;

/**
 * Value of the {@link #DAY_OF_WEEK} field indicating
 * Tuesday.
 */
public final static int TUESDAY = 3;

/**
 * Value of the {@link #DAY_OF_WEEK} field indicating
 * Wednesday.
 */
public final static int WEDNESDAY = 4;

/**
 * Value of the {@link #DAY_OF_WEEK} field indicating
 * Thursday.
 */
public final static int THURSDAY = 5;

/**
 * Value of the {@link #DAY_OF_WEEK} field indicating
 * Friday.
 */
public final static int FRIDAY = 6;

/**
 * Value of the {@link #DAY_OF_WEEK} field indicating
 * Saturday.
 */
public final static int SATURDAY = 7;

So, the day of the week for 1564088400000 returns 6( public final static int FRIDAY = 6; ). 因此, 1564088400000的星期返回6( public final static int FRIDAY = 6; )。 5. indice(6 - 1) of your mDaysOfTheWeek is Saturday . 5.您的mDaysOfTheWeekSaturday

It is returning 6, which is Friday, as expected. 正如预期的那样,它将返回6,即星期五。 But your array of strings mDaysOfTheWeek is set wrong. 但是您的字符串数组mDaysOfTheWeek设置错误。

Reference: 参考:

From the Class Calendar.java 从类Calendar.java

public final static int SUNDAY = 1;

/**
 * Value of the {@link #DAY_OF_WEEK} field indicating
 * Monday.
 */
public final static int MONDAY = 2;

/**
 * Value of the {@link #DAY_OF_WEEK} field indicating
 * Tuesday.
 */
public final static int TUESDAY = 3;

/**
 * Value of the {@link #DAY_OF_WEEK} field indicating
 * Wednesday.
 */
public final static int WEDNESDAY = 4;

/**
 * Value of the {@link #DAY_OF_WEEK} field indicating
 * Thursday.
 */
public final static int THURSDAY = 5;

/**
 * Value of the {@link #DAY_OF_WEEK} field indicating
 * Friday.
 */
public final static int FRIDAY = 6;

/**
 * Value of the {@link #DAY_OF_WEEK} field indicating
 * Saturday.
 */
public final static int SATURDAY = 7;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM