开发者

How to get first day of a given week number in Java

Let me explain myself. By knowing the week number and the year of a date:

Date curr = new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(curr);
int n开发者_开发百科week = cal.WEEK_OF_YEAR;
int year = cal.YEAR;

But now I don't know how to get the date of the first day of that week. I've been looking in Calendar, Date, DateFormat but nothing that may be useful...

Any suggestion? (working in Java)


Those fields does not return the values. Those are constants which identifies the fields in the Calendar object which you can get/set/add. To achieve what you want, you first need to get a Calendar, clear it and set the known values. It will automatically set the date to first day of that week.

// We know week number and year.
int week = 3;
int year = 2010;

// Get calendar, clear it and set week number and year.
Calendar calendar = Calendar.getInstance();
calendar.clear();
calendar.set(Calendar.WEEK_OF_YEAR, week);
calendar.set(Calendar.YEAR, year);

// Now get the first day of week.
Date date = calendar.getTime();

Please learn to read the javadocs to learn how to use classes/methods/fields and do not try to poke random in your IDE ;)

That said, the java.util.Date and java.util.Calendar are epic failures. If you can, consider switching to Joda Time.


Try this:

public static Calendar setWeekStart(Calendar calendar) {
  while (calendar.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) {
    calendar.add(Calendar.DATE, -1);
  }
  setDayStart(calendar); // method which sets H:M:S:ms to 0
  return calendar;
}


java.time

The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.

Also, quoted below is a notice from the home page of Joda-Time:

Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this project.

Solution using java.time, the modern Date-Time API:

import java.time.LocalDate;
import java.time.temporal.WeekFields;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        // Test
        int weekNumber = 34;
        int year = 2021;
        
        System.out.println(getFirstDayOfWeek(year, weekNumber, Locale.UK));
        System.out.println(getFirstDayOfWeek(year, weekNumber, Locale.US));
    }

    static LocalDate getFirstDayOfWeek(int year, int weekNumber, Locale locale) {
        return LocalDate
                .of(year, 2, 1)
                .with(WeekFields.of(locale).getFirstDayOfWeek())
                .with(WeekFields.of(locale).weekOfWeekBasedYear(), weekNumber);
    }
}

Output:

2021-08-23
2021-08-15

ONLINE DEMO

Note that the first day of the week is Locale-dependent e.g. it is Monday in the UK while Sunday in the US. As per the ISO 8601 standards, it is Monday. For comparison, check the US calendar and the UK calendar.

Learn more about the modern Date-Time API* from Trail: Date Time.


* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.


I haven't done much Date stuff in java but a solution might be:

cal.set(Calendar.DAY_OF_YEAR, cal.get(Calendar.DAY_OF_YEAR) - cal.get(Calendar.DAY_OF_WEEK));

Logic:

Get the day of the week and substract it from the current date (might need -1, depending on wether you need monday to be first day of the week or sunday)


Yet another way...

    GregorianCalendar cal = new GregorianCalendar();
    cal.clearTime();
    Integer correction = 1-cal.get(GregorianCalendar.DAY_OF_WEEK)
    cal.add(Calendar.DATE, correction);

cal is now the first day of the week

1-cal.get(GregorianCalendar.DAY_OF_WEEK)

evaluates to 1-1 for Sunday (first day of week in my Locale) and 1-2 for Monday, so this will give you the correction needed to rewind the clock back to Sunday


Be cautious with those, calendar.get(Calendar.WEEK_OF_YEAR) returns 1 if it is end of December and already a week that ends in the next year.

Using

//            cal2.set(Calendar.WEEK_OF_YEAR, cal.get(Calendar.WEEK_OF_YEAR));
//            cal2.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);

sets the cal2 date to e.g. end of 2009 on 29/12/2010 !!

I used this:

cal2.set(Calendar.DAY_OF_YEAR, cal.get(Calendar.DAY_OF_YEAR)); //to round at the start of day
cal2.set(Calendar.YEAR, cal.get(Calendar.YEAR));
cal2.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); //to round at the start of week

I also make sure that weeks in my calendars, no matter what locale they are in, are starting on Mondays:

cal.setFirstDayOfWeek(Calendar.MONDAY);
cal2.setFirstDayOfWeek(Calendar.MONDAY);


Try the Gregorian Calendar algorithm:

public int getFirstDay(int m, int year)
    {
        int k=1;
        int c, y, w, M=0;
        if(m>2 && m<=12) M=m-2;
        else if(m>0 && M<=2)
        {
            M=m+10;
            year-=1;
        }
        c=year/100;
        y=year%100;
        w=(int)((k+(Math.floor(2.6*M - 0.2))-2*c+y+(Math.floor(y/4))+(Math.floor(c/4)))%7);//a fantastic formula           
        if(w<0) w+=7;
        return w;//thus the day of the week is obtained!
    }


Here's some quick and dirty code to do this. This code creates a calendar object with the date of the current day, calculates the current day of the week, and subtracts the day of the week so you're on the first one (Sunday). Although I'm using DAY_OF_YEAR it goes across years fine (on 1/2/10 it'll return 12/27/09 which is right).

import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;


public class DOW {

    public static void main(String[] args) {
        DOW dow = new DOW();
        dow.doIt();
        System.exit(0);
    }

    private void doIt() {
        Date curr = new Date(); 
        Calendar cal = Calendar.getInstance(); 
        cal.setTime(curr); 
        int currentDOW = cal.get(Calendar.DAY_OF_WEEK);
        cal.add(Calendar.DAY_OF_YEAR, (currentDOW * -1)+1);

        Format formatter = new SimpleDateFormat("MM/dd/yy");
        System.out.println("First day of week="+formatter.format(cal.getTime()));
    }
}
0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜