-1

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.

I've tried using DateFormat or other date processing classes from Java, but my current min API for the android app is 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

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. 6 is the result given back.

private final String[] mDaysOfTheWeek
        = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}; 
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
David Buzatu
  • 624
  • 8
  • 18
  • FYI, you can use backticks ( ` ) to format inline code. – cameron1024 Jul 26 '19 at 13:10
  • https://stackoverflow.com/a/16541525/4398114 You can use this to get the name of the day directly – Allinone51 Jul 26 '19 at 13:13
  • 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` – David Buzatu Jul 26 '19 at 13:15
  • @DavidBuzatu What result are you getting? 6? [At least it's supposed to be 6](https://docs.oracle.com/javase/7/docs/api/constant-values.html#java.util.Calendar.FRIDAY). – Joachim Isaksson Jul 26 '19 at 13:17
  • What does `mDaysOfTheWeek` includes in array? – faranjit Jul 26 '19 at 13:18
  • @Joachim Isaksson, yes, 6 is the result given back. `private final String[] mDaysOfTheWeek = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};` – David Buzatu Jul 26 '19 at 13:19
  • Sunday is day 1, saturday is day 7, the others inbetween. There is no day zero. `private final String[] mDaysOfTheWeek = {"NONE", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};` – Joachim Isaksson Jul 26 '19 at 13:20
  • Oh... I thought Monday is day 1 (East European here). Thank you for the remark @Joachim Isaksson – David Buzatu Jul 26 '19 at 13:22
  • 1
    You are of course correct that numbering the days from Sunday is an American design error as long as the international standard says that Monday is the first day of the week (it’s just one of many design problems with the `Calendar` class). – Ole V.V. Jul 26 '19 at 13:31

3 Answers3

1

tl;dr

It should return: 5, which is Friday, … 6 is the result given back.

The terrible Calendar class has many problems.

  • One problem is its use of shifting behavior implicitly depending on the JVM’s current default locale. 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.
  • Another problem is crazy zero-based counting, 0-6 for days of the week, and 0-11 for months.

Use java.time instead. The counting is sane (1-7 for Monday-Sunday), and the time zone behavior can be made predictable and explicit.

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.

Friday

If you insist on a number 1-7 for Monday-Sunday, call getValue instead of .getDisplayName.

.getValue()

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. Never use Date or Calendar.

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. An Instant represents a moment in UTC, a specific point on the timeline.

Instant instant = Instant.ofEpochMilli( 1_564_088_400_000L ) ;

See this code run live at IdeOne.com.

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. 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(!).

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 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.

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.

Day of week

Interrogate for the day-of-week using the DayOfWeek enum.

DayOfWeek dow = zdt.getDayOfWeek() ;

or example, for the date: 1564088400000 It should return: 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.

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.

int dayOfWeekNumber = dow.getValue() ; 

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

No need to roll-your-own. Use the DayOfWeek enum.


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • Thank you for this complete answer with so many details I've read about in others topics, but didn't quite get how it works. The only problem I have with this java.time and why I didn't use it, is that android studio prompts that my current minim API is 22, but for `Instant instant = Instant.getTimeInEpoch()' it marks it as error because only from API 26 it can be used – David Buzatu Jul 29 '19 at 09:39
  • @DavidBuzatu See the bullets at the end of my Answer. – Basil Bourque Jul 29 '19 at 16:07
0

If you look at to Calendar class

/**
 * 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;). 5. indice(6 - 1) of your mDaysOfTheWeek is Saturday.

faranjit
  • 1,567
  • 1
  • 15
  • 22
  • As @Joachim Isaksson pointed out earlier, that was my mistake. Thank you – David Buzatu Jul 26 '19 at 13:23
  • Yeah, he was posted while i am typing answer :) – faranjit Jul 26 '19 at 13:27
  • FYI, the terribly troublesome date-time classes such as [`java.util.Date`](https://docs.oracle.com/javase/10/docs/api/java/util/Date.html), [`java.util.Calendar`](https://docs.oracle.com/javase/10/docs/api/java/util/Calendar.html), and `java.text.SimpleDateFormat` are now [legacy](https://en.wikipedia.org/wiki/Legacy_system), supplanted by the [*java.time*](https://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html) classes built into Java 8 and later. See [*Tutorial* by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). – Basil Bourque Jul 27 '19 at 19:22
0

It is returning 6, which is Friday, as expected. But your array of strings mDaysOfTheWeek is set wrong.

Reference:

From the Class 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;
touhid udoy
  • 4,005
  • 2
  • 18
  • 31