Amar
Amar

Reputation: 12020

Get Date in Java given Week number, week day and year

Given Week of the year, the week day and the year, how can we get the Date in Java?

With Jodatime, I tried the following:

DateTime dt = new DateTime();
dt.withYear(year);
dt.withWeekOfWeekyear(weekOfYear);
dt.withDayOfWeek(weekDay);
DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern("yyMMdd");
System.out.println(dateTimeFormatter.print(dt));

But it gets the current Date!

Upvotes: 3

Views: 8345

Answers (7)

Arvind Kumar Avinash
Arvind Kumar Avinash

Reputation: 79560

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.DayOfWeek;
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(getLocalDate(weekNumber, DayOfWeek.TUESDAY, year, Locale.UK));
        System.out.println(getLocalDate(weekNumber, DayOfWeek.TUESDAY, year, Locale.US));
        
        System.out.println(getLocalDate(weekNumber, DayOfWeek.SUNDAY, year, Locale.UK));
        System.out.println(getLocalDate(weekNumber, DayOfWeek.SUNDAY, year, Locale.US));        
    }

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

Output:

2021-08-24
2021-08-17
2021-08-29
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. Accordingly, the date will vary as shown in the example above.

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.

Upvotes: 2

Neet
Neet

Reputation: 4057

JodaTime returns a changed copy, so do:

DateTime dt = new DateTime()
    .withWeekyear(year)
    .withWeekOfWeekyear(weekOfYear)
    .withDayOfWeek(weekDay);
DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern("yyMMdd");
System.out.println(dateTimeFormatter.print(dt));

And this should work as expected.

Upvotes: 6

LiuJian
LiuJian

Reputation: 155

The accepted answer has bug..withYear(year) should be withWeekyear(year). @Neet please update it.

Upvotes: 5

Basil Bourque
Basil Bourque

Reputation: 340070

tl;dr

YearWeek.of( 2017 , 1 )
        .atDay( DayOfWeek.TUESDAY ) 
        .format( DateTimeFormatter.ofPattern( "uuMMdd" ) ) 

“Week” ambiguous

The word 'week' is ambiguous. Do you mean week number 1 contains January 1? Or week number 1 contains the first of a particular day of year such as Sunday or Monday?

Or do you mean a standard ISO 8601 week? To quote from YearWeek doc:

ISO-8601 defines the week as always starting with Monday. The first week is the week which contains the first Thursday of the calendar year. As such, the week-based-year used in this class does not align with the calendar year.

java.time

The modern approach uses the java.time classes.

ThreeTen-Extra

The ThreeTen-Extra project extends java.time with additional functionality. This includes a handy YearWeek class, just what we need for this Question.

Specify your week-based year number and your week number.

YearWeek yw = YearWeek.of( 2017 , 1 ) ; 

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

You can ask the YearWeek object to determine the date of a day contained within its week. Specify a DayOfWeek enum object. Note that a DayOfWeek is an object rather than a mere integer or string, providing for type-safety and valid values.

LocalDate ld = yw.atDay( DayOfWeek.TUESDAY ) ; 

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.

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

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

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.

Upvotes: 1

Linus
Linus

Reputation: 1518

Here is a simple example of how to do it without JodaTime:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Snippet {
    public static void main(String args[]) {
        String year = "2013";
        String week_of_year = "46";
        String day_of_week = "4";
        String yearweekday = year + week_of_year + day_of_week;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyywwu");
        Date date = null;
        try {
            date = sdf.parse(yearweekday);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        System.out.println(date);
    }
}

Good luck!

Upvotes: 1

Manish Verma
Manish Verma

Reputation: 781

We can also use this native java code using Calendar class:

    SimpleDateFormat sdf = new SimpleDateFormat("MM dd yyyy");
    Calendar cal = Calendar.getInstance();
    cal.set(Calendar.WEEK_OF_YEAR, 23);
    cal.set(Calendar.DAY_OF_WEEK, 3);
    cal.set(Calendar.YEAR,2013);
    System.out.println(sdf.format(cal.getTime()));

Upvotes: 1

Julian
Julian

Reputation: 137

You need to reassign the date afterwards! the dt.with*() methods simply make a copy of the date.

try

DateTime dt = new DateTime();
dt = dt.withYear(year);
dt = dt.withWeekOfWeekyear(weekOfYear);
dt = dt.withDayOfWeek(weekDay);
DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern("yyMMdd");
System.out.println(dateTimeFormatter.print(dt));

Upvotes: 1

Related Questions