开发者

Start of week for locale using Joda-Time

How do you determine which day of the week is considered the “start” according to a given Locale using开发者_如何学Go 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


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.


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.


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)
}


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


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);
}


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


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();


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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜