Start of week for locale using Joda-Time
Asked Answered
N

8

59

How do you determine which day of the week is considered the “start” according to a given Locale using Joda-Time?

Point: Most countries use the international standard Monday as first day of week (!). A bunch others use Sunday (notably USA). Others apparently Saturday. Some apparently Wednesday?!

Wikipedia "Seven-day week"#Week_number

Nymph answered 26/11, 2009 at 6:36 Comment(6)
Read my question again, please. I believe I actually drove the point home hard enough that it would be simply impossible to misunderstand it for the question the two of you come up with. Amazingly, I was mistaken. Here goes again: Some locales (i.e. USA) use Sunday as first day of week. Others use the ISO-standard Monday as first day of week. How do I query Joda Time for this? With Java, it is damn easy: java.sun.com/javase/6/docs/api/java/util/… So: Calendar.getInstance(Locale.US).getFirstDayOfWeek(). With Joda?Nymph
Why not just use Calendar.getInstance(Locale.US).getFirstDayOfWeek()?Fold
Because if I want to use Joda Time, I want to use it "all the way through", not mixing two completely different libraries.Nymph
I think Joda Time should be used with the Java Standard libs, like Calendar. The Homepage says "... Joda-Time comes with out-of-the-box JDK interoperability.".Handpick
Yes, that statement means that you can easily go back and forth between them. It does not, AFAICT, mean that you should mix them. To me, it seems like I can do everything with Joda Time, pure, except find the first day of the week!Nymph
Calendar.getFirstDayOfWeek() will return different number than Joda's DateTimeConstants. For example, Calendar.SUNDAY==1 (US default), while DateTimeConstants.SUNDAY==7 (ISO).Loveliesbleeding
I
46

Joda-Time uses the ISO standard Monday to Sunday week.

It does not have the ability to obtain the first day of week, nor to return the day of week index based on any day other than the standard Monday. Finally, weeks are always calculated wrt ISO rules.

Innoxious answered 27/11, 2009 at 11:38 Comment(3)
Then I have to ask - mustn't this be seen as a clear deficiency with Joda Time? Seriously, for "printed calendars" (that is, those you hang on your kitchen, those that you pick from in flight-schedule-webapps), I find it severely annoying when a calendar shows Sunday as first day of week - I do actually get into problems because of it. So I assume that it must be exactly the same for Americans when they are presented with calendars where weeks start on Monday: Everything becomes "one day early", so to speak - when looking at the third "box" of a week, an American assumes it is Tuesday.Nymph
@Nymph Why should it be a deficiency? This only determines what number corresponds to what day of the week. Eg: 1=MONDAY.Massarelli
Because, @CristianVrabie, it makes working with the library harder if you have to find the first day of the week for a given date. For locales with Monday, you can just invoke LocalDate.now().withDayOfWeek(DateTimeConstants.MONDAY), but this won’t work if you actually need a Sunday instead. You have to check whether it already is Sunday, and if not, go to Sunday and one week back. It sucks. However, note that Java’s calendar sucks as well; even worse, it lets you believe it works while it doesn’t, see https://mcmap.net/q/331276/-java-how-to-calculate-the-first-and-last-day-of-each-weekAdolphus
M
16

There's no reason you can't make use of the JDK at least to find the "customary start of the week" for the given Locale. The only tricky part is translating constants for weekdays, where both are 1 through 7, but java.util.Calendar is shifted by one, with Calendar.MONDAY = 2 vs. DateTimeConstants.MONDAY = 1.

Anyway, use this function:

/**
 * Gets the first day of the week, in the default locale.
 *
 * @return a value in the range of {@link DateTimeConstants#MONDAY} to
 *         {@link DateTimeConstants#SUNDAY}.
 */
private static final int getFirstDayOfWeek() {
  return ((Calendar.getInstance().getFirstDayOfWeek() + 5) % 7) + 1;
}

Add a Locale to Calendar.getInstance() to get a result for some Locale other than the default.

Madame answered 2/11, 2012 at 19:36 Comment(2)
This I wrote in a comment to the question 29. nov. 2009.Nymph
Very good answer that provides the OP with what he says he's looking for. One suggestion: specify the package name explicitly, "java.util.Calendar", so a purest does not need to have his sensitivites violated with an undesired using statement at the top of his code. :-)Palpitation
E
7

Here is how one might work around Joda time to get the U.S. first day of the week:

DateTime getFirstDayOfWeek(DateTime other) {
  if(other.dayOfWeek.get == 7)
    return other;
  else
    return other.minusWeeks(1).withDayOfWeek(7);
}

Or in Scala

def getFirstDayOfWeek(other: DateTime) = other.dayOfWeek.get match {
    case 7 => other
    case _ => other.minusWeeks(1).withDayOfWeek(7)
}
Edlun answered 23/10, 2014 at 16:45 Comment(0)
C
2

Seems like you're out of luck, it looks like all of the provided Chronologies inherit the implementation from baseChronology, which supports only ISO definitions, i.e. Monday=1 ... Sunday=7.

You would have to define your own LocaleChronology, possibly modeled on StrictChronology or LenientChronology, add a factory method:

public static LocaleChronology getInstance(Chronology base, Locale locale)

and override the implementation of

public final DateTimeField dayOfWeek()

with a re-implementation of java.util.Calendar.setWeekCountData(Locale desiredLocale) which relies on sun.util.resources.LocaleData..getCalendarData(desiredLocale).

Circumpolar answered 26/11, 2009 at 14:38 Comment(6)
I don't quite get that. Us Norwegians and them Americans do agree that 2009-11-26 is a Thursday - it is only that when we display a full week - 7 days in a row - us Europeans start with some Monday and finish of with the following Sunday (i.e. "Weekend" being Saturday and Sunday, right?), while Americans start with some Sunday and finish with the following Saturday. This is exactly the same as Norwegians writing 26/11 2009, Swedish 2009-11-26 (they're logical over there!), and Americans 11/26 2009 (?!). It is merely a display issue, not a calculation issue.Nymph
All Chronologies will show 2009-11-26 as a Thursday, and this should show as week 48 of 53 in the ISOChronology. Now if we were to ask what is the firstDayOfWeek(48), the answer would depend on the locale: US = Sun 2009-11-22 NO = Mon 2009-11-23Circumpolar
The problem seems similar to different programming languages that use different values for the first position in an array, e.g. java is zero based array[0], whereas pascal and cobol are 1 based array[1]. So if you are given a random element > 1 in an array with a size of 7, the way that you determine how to go back to the first position would depend on your programming language: java: fdow(day[3]) = day[3-3] cobol/pascal: fdow(day[3]) = day[3-2]Circumpolar
I hope that analogy isn't too obscure, similarly the first day of the week in different locales will differ because some go back to mon and others go back to sun, so the calulation is different depending on the locale.Circumpolar
Thanks for answer and comments!. But my point is still that it does not matter that Monday is set as 1 and Sunday as 7 in Joda Time. For java, Monday is 2, and Sunday 1 (and Saturday 7), and it is like that no matter what Locale you operate under. You can however simply ask a Calendar instantiated with a given Locale "what is customarily the first day of the week for this Locale", and hence make a Calendar-chooser which makes sense to the users of that locale. (My previous comment about this not affecting calculations is not quite true, though: The WEEK NUMBER is affected by this, I believe.)Nymph
Where do you have firstDayOfWeek(48)? I didn't quite understand this. You don't need an argument - it would be the same for all 1-53, always? But anyway, the more I look into this, the more it seems like Joda Time simply does not handle this problem? Isn't that exceptionally strange, given that it has been hailed as the replacement of java's Calendar stuff? .. and not tend to people of the USA?Nymph
D
0

This is what I came up with. The startOfWeek will always be the start of a Sunday and the endOfweek will always be an end of a Saturday(Start a of Monday).

DateTime startOfWeek;
DateTime endOfWeek;
// make sure Sunday is the first day of the week, not Monday
if (dateTime.getDayOfWeek() == 7) {
    startOfWeek = dateTime.plusDays(1).weekOfWeekyear().roundFloorCopy().minusDays(1);
    endOfWeek = dateTime.plusDays(1).weekOfWeekyear().roundCeilingCopy().minusDays(1);
} else {
    startOfWeek = dateTime.weekOfWeekyear().roundFloorCopy().minusDays(1);
    endOfWeek = dateTime.weekOfWeekyear().roundCeilingCopy().minusDays(1);
}
Dituri answered 27/12, 2019 at 0:32 Comment(0)
H
0

Here is the Scala code to get start and end day of week dynamically.

Note:- Make sure start and end are in order for example when start day is Sunday then Monday is end day of week

def shiftWeeksBy(startDayOfWeek: Int, currentWeekDay: Int) : Int = (startDayOfWeek, currentWeekDay) match {
  case (s, c) if s <= c  | s == 1 => 0 //start day of week is Monday -OR- start day of week <= current week day
  case _ => 1
}

def getStartAndEndDays(initialTime: DateTime, startDayOfWeek: Int, endDayOfWeek: Int): (Option[DateTime], Option[DateTime]) = {
   val currentDateWeekDay = initialTime.dayOfWeek.get
   (Some(initialTime.minusWeeks(shiftWeeksBy(startDayOfWeek, currentDateWeekDay)).withDayOfWeek(startDayOfWeek).withTimeAtStartOfDay()),
       Some(initialTime.plusWeeks(shiftWeeksBy(currentDateWeekDay, endDayOfWeek)).withDayOfWeek(endDayOfWeek)))
}

Output:- For 5th Jan 2021 start day of week is Thursday and end day of week is Wednesday then week begins with 2020-12-31 and end with 2021-01-06.

scala> getStartAndEndDays(new DateTime("2021-01-05T00:00:00.000"), 4, 3)
res5: (Option[org.joda.time.DateTime], Option[org.joda.time.DateTime]) = (Some(2020-12-31T00:00:00.000+05:30),Some(2021-01-06T00:00:00.000+05:30))
Honeysweet answered 23/11, 2021 at 6:24 Comment(0)
M
-1

So your question is, how to get the DayOfWeek from a Joda DateTime object? What about this:

DateTime dt = new DateTime().withYear(2009).plusDays(111);
dt.toGregorianCalendar().getFirstDayOfWeek();
Manriquez answered 26/11, 2009 at 9:58 Comment(4)
No, that is not my question. My question is: Given Locale.US (and NOTHING ELSE), what is the first day of the week? And I want Joda Time to tell me - not java std. libraries. Joda Time's chronologies seems to all state that Monday is the first day of the week (which is what that ISO8601 standard says). Is this not possible? Does not Joda Time know that Americans prefer to see their calendars with "Sunday" as the week's first day, while (most of) us Europeans become really upset about that, and want "Monday" to be the start of a week? I find that unbelievable, as Joda Time seems complete.Nymph
Why you not just use the Java standard libraries? Maybe they don't implemented it, because it is already there. I really don't get your point.Handpick
Do you know Joda Time? They would not have needed to implement ANYTHING, as everything IS possible in the java std. libs. My question thus still stands: If it is really not possible with Joda Time, then Joda Time is inclomplete, lacking. I find that hard to believe, but it might be true.Nymph
Whatever, the whole discussion seems absolutely pointless to me. Joda Time should, in my opinon, be used because the original implementation is a great PITA. However, for parts that are not provided, you can easily fall back. I don't think it is necessary to duplicate every aspect, just for the sake of completeness. If the firstDayOfWeek method, is really the one and only missing method, I'm getting your point. But I don't understand, why you're so upset and passionated about that...Handpick
A
-1

I used the following stub in Scala to obtain first and last days of the week from Joda DateTime

val today: DateTime = new DateTime()
val dayOfWeek: DateTime.Property = today.dayOfWeek()

val firstDayOfWeek: DateTime = dayOfWeek.withMinimumValue().minusDays(1)
val lastDayOfWeek: DateTime = dayOfWeek.withMaximumValue().minusDays(1)

Note: The minusDays(1) is only meant to make the week span from Sunday to Saturday (instead of the default Monday to Sunday known to Joda). For US (and other similar) locales, you can ignore this part

Aachen answered 15/12, 2017 at 9:21 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.