Pergunta

Today is 2014-04-06 (Sunday).

The output I get from using the code below is:

Start Date = 2014-04-07
End Date = 2014-04-13

This is the output I would like to get instead:

Start Date = 2014-03-31
End Date = 2014-04-06

How can I achieve this?

This is the code I have completed so far:

// Get calendar set to current date and time
Calendar c = GregorianCalendar.getInstance();

System.out.println("Current week = " + Calendar.DAY_OF_WEEK);

// Set the calendar to monday of the current week
c.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
System.out.println("Current week = " + Calendar.DAY_OF_WEEK);

// Print dates of the current week starting on Monday
DateFormat df = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
String startDate = "", endDate = "";

startDate = df.format(c.getTime());
c.add(Calendar.DATE, 6);
endDate = df.format(c.getTime());

System.out.println("Start Date = " + startDate);
System.out.println("End Date = " + endDate);
Foi útil?

Solução

Updated answer using Java 8

Using Java 8 and keeping the same principle as before (the first day of the week depends on your Locale), you should consider using the following:

Obtain the first and last DayOfWeek for a specific Locale

final DayOfWeek firstDayOfWeek = WeekFields.of(locale).getFirstDayOfWeek();
final DayOfWeek lastDayOfWeek = DayOfWeek.of(((firstDayOfWeek.getValue() + 5) % DayOfWeek.values().length) + 1);

Query for this week's first and last day

LocalDate.now(/* tz */).with(TemporalAdjusters.previousOrSame(firstDayOfWeek)); // first day
LocalDate.now(/* tz */).with(TemporalAdjusters.nextOrSame(lastDayOfWeek));      // last day

Demonstration

Consider the following class:

private static class ThisLocalizedWeek {

    // Try and always specify the time zone you're working with
    private final static ZoneId TZ = ZoneId.of("Pacific/Auckland");

    private final Locale locale;
    private final DayOfWeek firstDayOfWeek;
    private final DayOfWeek lastDayOfWeek;

    public ThisLocalizedWeek(final Locale locale) {
        this.locale = locale;
        this.firstDayOfWeek = WeekFields.of(locale).getFirstDayOfWeek();
        this.lastDayOfWeek = DayOfWeek.of(((this.firstDayOfWeek.getValue() + 5) % DayOfWeek.values().length) + 1);
    }

    public LocalDate getFirstDay() {
        return LocalDate.now(TZ).with(TemporalAdjusters.previousOrSame(this.firstDayOfWeek));
    }

    public LocalDate getLastDay() {
        return LocalDate.now(TZ).with(TemporalAdjusters.nextOrSame(this.lastDayOfWeek));
    }

    @Override
    public String toString() {
        return String.format(   "The %s week starts on %s and ends on %s",
                                this.locale.getDisplayName(),
                                this.firstDayOfWeek,
                                this.lastDayOfWeek);
    }
}

We can demonstrate its usage as follows:

final ThisLocalizedWeek usWeek = new ThisLocalizedWeek(Locale.US);
System.out.println(usWeek);
// The English (United States) week starts on SUNDAY and ends on SATURDAY
System.out.println(usWeek.getFirstDay()); // 2018-01-14
System.out.println(usWeek.getLastDay());  // 2018-01-20

final ThisLocalizedWeek frenchWeek = new ThisLocalizedWeek(Locale.FRANCE);
System.out.println(frenchWeek);
// The French (France) week starts on MONDAY and ends on SUNDAY
System.out.println(frenchWeek.getFirstDay()); // 2018-01-15
System.out.println(frenchWeek.getLastDay());  // 2018-01-21

Original Java 7 answer (outdated)

Simply use:

c.setFirstDayOfWeek(Calendar.MONDAY);

Explanation:

Right now, your first day of week is set on Calendar.SUNDAY. This is a setting that depends on your Locale.

Thus, a better alternative would be to initialise your Calendar specifying the Locale you're interested in.
For example:

Calendar c = GregorianCalendar.getInstance(Locale.US);

... would give you your current output, while:

Calendar c = GregorianCalendar.getInstance(Locale.FRANCE);

... would give you your expected output.

Outras dicas

Well, looks like you got your answer. Here's an add-on, using java.time in Java 8 and later. (See Tutorial)

import java.time.DayOfWeek;
import java.time.LocalDate;

public class MondaySunday
{
  public static void main(String[] args)
  {
    LocalDate today = LocalDate.now();

    // Go backward to get Monday
    LocalDate monday = today;
    while (monday.getDayOfWeek() != DayOfWeek.MONDAY)
    {
      monday = monday.minusDays(1);
    }

    // Go forward to get Sunday
    LocalDate sunday = today;
    while (sunday.getDayOfWeek() != DayOfWeek.SUNDAY)
    {
      sunday = sunday.plusDays(1);
    }

    System.out.println("Today: " + today);
    System.out.println("Monday of the Week: " + monday);
    System.out.println("Sunday of the Week: " + sunday);
  }
}

Another way of doing it, using temporal adjusters.

import java.time.LocalDate;

import static java.time.DayOfWeek.MONDAY;
import static java.time.DayOfWeek.SUNDAY;
import static java.time.temporal.TemporalAdjusters.nextOrSame;
import static java.time.temporal.TemporalAdjusters.previousOrSame;

public class MondaySunday
{
  public static void main(String[] args)
  {
    LocalDate today = LocalDate.now();

    LocalDate monday = today.with(previousOrSame(MONDAY));
    LocalDate sunday = today.with(nextOrSame(SUNDAY));

    System.out.println("Today: " + today);
    System.out.println("Monday of the Week: " + monday);
    System.out.println("Sunday of the Week: " + sunday);
  }
}

This is what I did to get start and end date for current week.

public static Date getWeekStartDate() {
    Calendar calendar = Calendar.getInstance();
    while (calendar.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) {
        calendar.add(Calendar.DATE, -1);
    }
    return calendar.getTime();
}

public static Date getWeekEndDate() {
    Calendar calendar = Calendar.getInstance();
    while (calendar.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) {
        calendar.add(Calendar.DATE, 1);
    }
    calendar.add(Calendar.DATE, -1);
    return calendar.getTime();
}

tl;dr

Use the handy YearWeek class from ThreeTen-Extra library to represent an entire week. Then ask it to determine the date for any day-of-week within that week.

org.threeten.extra.YearWeek          // Handy class representing a standard ISO 8601 week. Class found in the *ThreeTen-Extra* project, led by the same man as led JSR 310 and the *java.time* implementation.
.now(                                // Get the current week as seen in the wall-clock time used by the people of a certain region (a time zone). 
    ZoneId.of( "America/Chicago" ) 
)                                    // Returns a `YearWeek` object.
.atDay(                              // Determine the date for a certain day within that week.
    DayOfWeek.MONDAY                 // Use the `java.time.DayOfWeek` enum to specify which day-of-week.
)                                    // Returns a `LocalDate` object.

LocalDate

The LocalDate class represents a date-only value without time-of-day and without time zone or offset-from-UTC.

A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.

If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment during runtime(!), so your results may vary. Better to specify your desired/expected time zone explicitly as an argument. If critical, confirm the zone with your user.

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

If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the code becomes ambiguous to read in that we do not know for certain if you intended to use the default or if you, like so many programmers, were unaware of the issue.

ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.

Or specify a date. You may set the month by a number, with sane numbering 1-12 for January-December.

LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ;  // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.

Or, better, use the Month enum objects pre-defined, one for each month of the year. Tip: Use these Month objects throughout your codebase rather than a mere integer number to make your code more self-documenting, ensure valid values, and provide type-safety. Ditto for Year & YearMonth.

LocalDate ld = LocalDate.of( 2014 , Month.APRIL , 6 ) ;

YearWeek

Your definition of a week running from Monday to Sunday matches that of the ISO 8601 standard.

Add the ThreeTen-Extra library to your project to access the YearWeek class representing the standard week.

YearWeek week = YearWeek.from( ld ) ;  // Determine the week of a certain date.

Or get today's week.

YearWeek week = YearWeek.now( z ) ;

Get the date for any day of the week. Specify which day by using DayOfWeek enum.

LocalDate firstOfWeek = week.atDay( DayOfWeek.MONDAY ) ;
LocalDate lastOfWeek = week.atDay( DayOfWeek.SUNDAY ) ;

I used below method to check if a given date falls in current week

public boolean isDateInCurrentWeek(Date date) 
{
        Date currentWeekStart, currentWeekEnd;

        Calendar currentCalendar = Calendar.getInstance();
        currentCalendar.setFirstDayOfWeek(Calendar.MONDAY);
        while(currentCalendar.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY)
        {
            currentCalendar.add(Calendar.DATE,-1);//go one day before
        }
        currentWeekStart = currentCalendar.getTime();

        currentCalendar.add(Calendar.DATE, 6); //add 6 days after Monday
        currentWeekEnd = currentCalendar.getTime();

        Calendar targetCalendar = Calendar.getInstance();
        targetCalendar.setFirstDayOfWeek(Calendar.MONDAY);
        targetCalendar.setTime(date);


        Calendar tempCal = Calendar.getInstance();
        tempCal.setTime(currentWeekStart);

        boolean result = false;
        while(!(tempCal.getTime().after(currentWeekEnd)))
        {
            if(tempCal.get(Calendar.DAY_OF_YEAR)==targetCalendar.get(Calendar.DAY_OF_YEAR))
            {
                result=true;
                break;
            }
            tempCal.add(Calendar.DATE,1);//advance date by 1
        }

        return result;
    }
Calendar privCalendar = Calendar.getInstance();
Date fdow, ldow;
int dayofWeek = privCalendar.get ( Calendar.DAY_OF_WEEK );
Date fdow, ldow;

                    if( dayofWeek == Calendar.SUNDAY ) {

                        privCalendar.add ( Calendar.DATE, -1 * (dayofWeek -
                                Calendar.MONDAY ) - 7 );

                        fdow = privCalendar.getTime();

                        privCalendar.add( Calendar.DATE, 6 );

                        ldow = privCalendar.getTime();
                    } else {

                        privCalendar.add ( Calendar.DATE, -1 * (dayofWeek -
                                Calendar.MONDAY ) );

                        fdow = privCalendar.getTime();

                        privCalendar.add( Calendar.DATE, 6 );

                        ldow = privCalendar.getTime();
                    }
/**
 * Get the date of the first day in the week of the provided date
 * @param date A date in the interested week
 * @return The date of the first week day
 */
public static Date getWeekStartDate(Date date){
    Calendar cal = Calendar.getInstance();
    cal.setTime(date);
    cal.set(Calendar.DAY_OF_WEEK, getFirstWeekDay());
    return cal.getTime();
}

/**
 * Get the date of the last day in the week of the provided date
 * @param date A date in the interested week
 * @return The date of the last week day
 */
public static Date getWeekEndDate(Date date){
    Calendar cal = Calendar.getInstance();
    cal.setTime(date);
    cal.add(Calendar.DATE, 6);// last day of week
    return cal.getTime();
}

Date now = new Date(); // any date
Date weekStartDate = getWeekStartDate(now);
Date weekEndDate = getWeekEndDate(now);

// if you don't want the end date to be in the future
if(weekEndDate.after(now))
    weekEndDate = now;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top