简体   繁体   中英

How to change the date of a Calendar instance in Java?

I have a class DayOfWeek which takes a date from the user and prints the day of the week on that date.

For example the user will enter his date as: (with the format MM DD YYYY )

07 22 2016

and the output should be

FRIDAY

This is my class:

public class DayOfWeek{
    public static void main(String[] args){
        System.out.println("Enter the date (Format: MM DD YYYY) :");
        Scanner sc = new Scanner(System.in);
        String month = sc.next();
        String day = sc.next();
        String year = sc.next();
        int m = Integer.parseInt(month);
        int d = Integer.parseInt(day);
        int y = Integer.parseInt(year);
        Calendar cal = Calendar.getInstance();
        Date date = new Date(y, m, d);
        cal.setTime(date);
        int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
        SimpleDateFormat sdf = new SimpleDateFormat("EEEE");
        System.out.println((sdf.format(dayOfWeek)).toUpperCase());
    }
}

However when I enter the date stated above ( 07 22 2016 ), I don't get the required output ( FRIDAY ). Instead the output is the current day of week on my system. I am totally stuck on what the problem is.

You're currently passing an int to SimpleDateFormat ... you should pass the Date value. You don't need a Calendar at all for that:

// BAD CODE: DON'T USE - KEEP READING
import java.text.*;
import java.util.*;

public class DayOfWeek {
    public static void main(String[] args){
        System.out.println("Enter the date (Format: MM DD YYYY) :");
        Scanner sc = new Scanner(System.in);
        String month = sc.next();
        String day = sc.next();
        String year = sc.next();
        int m = Integer.parseInt(month);
        int d = Integer.parseInt(day);
        int y = Integer.parseInt(year);
        // Note the changes here
        Date date = new Date(y - 1900, m - 1, d);
        SimpleDateFormat sdf = new SimpleDateFormat("EEEE");
        System.out.println(sdf.format(date).toUpperCase());
    }
}

I've put the warning there because you're using a deprecated Date constructor - and it's deprecated for good reasons. Basically, java.util.Date is a terrible API and you should avoid using it if you possibly can. Your original call to new Date(y, m, d) was broken because the first parameter to java.util.Date(int, int, int) represents the year with a 1900 base (so a value of 117 means year 2017) and the second parameter represents the month with a 0 base (so a value of 6 means July). Then there's the implicit time zone conversion, which you really don't want.

You'd be much better off using java.time , and in this case the LocalDate class:

import java.time.*;
import java.time.format.*;
import java.util.*;

public class DayOfWeek {
    public static void main(String[] args){
        System.out.println("Enter the date (Format: MM DD YYYY) :");
        Scanner sc = new Scanner(System.in);
        String month = sc.next();
        String day = sc.next();
        String year = sc.next();
        int m = Integer.parseInt(month);
        int d = Integer.parseInt(day);
        int y = Integer.parseInt(year);
        LocalDate date = LocalDate.of(y, m, d);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEEE");
        System.out.println(formatter.format(date).toUpperCase());
    }
}

Finally, your approach to parsing the user input isn't ideal either - I'd suggest using a DateTimeFormatter for that, too:

import java.time.*;
import java.time.format.*;

public class DayOfWeek {
    public static void main(String[] args){
        System.out.println("Enter the date (Format: MM DD YYYY) :");
        DateTimeFormatter parser = DateTimeFormatter.ofPattern("MM dd yyyy");
        Scanner sc = new Scanner(System.in);
        String line = sc.nextLine();
        LocalDate date = LocalDate.parse(line, parser);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEEE");
        System.out.println(formatter.format(date).toUpperCase());
    }
}
Calendar c = Calendar.getInstance();
c.setTime(yourDate);
int dayOfWeek = c.get(Calendar.DAY_OF_WEEK);

if you need the output to be Tue rather than 3 (Days of week are indexed starting at (1), instead of going through a calendar, just reformat the string: new SimpleDateFormat("EE").format(date) (EE meaning "day of week, short version").

Note As pointed by Jon Try and use the latest Date Time Formatter Api for this purpose the Date Api is depricated .

If you have your input as string, rather than Date, you should use SimpleDateFormat to parse it

: new SimpleDateFormat("dd/M/yyyy").parse(dateString)

@JonSkeet's answer is correct and already explains all the problems of the old API and how to use the new one. I'd just like to add another approach with java.time classes.

If you want just to get a String with the day of the week, you can skip the creation of a LocalDate and get directly a java.time.DayOfWeek .

The first part is the same (get the input from the Scanner and create a DateTimeFormatter to parse it).

Then I create a java.time.DayOfWeek from the parsed input, using the from method. So I call getDisplayName , using java.time.format.TextStyle (which is equivalent to EEEE format in @JonSkeet's answer ) and a java.util.Locale to make it explicit that I want the day of week's names in English.

// read line from input
Scanner sc = new Scanner(System.in);
// get "07 22 2016" from the scanner
String line = sc.nextLine();
// formatter to parse the input
DateTimeFormatter parser = DateTimeFormatter.ofPattern("MM dd yyyy");
// get the day of the week
DayOfWeek dow = DayOfWeek.from(parser.parse(line));
// get day of week's name
String output = dow.getDisplayName(TextStyle.FULL, Locale.ENGLISH).toUpperCase();

The value of output variable will be FRIDAY - note that I also called toUpperCase() , because the result of getDisplayName is Friday .

The Locale is also important. If you don't specify a locale, it'll use the system's default, and it's not guaranteed to always be English . And it can also be changed without notice, even at runtime, so it's better to make it explicit in your code.


Notes:

  • The code above will also work if you want to change the language (just use a different Locale ). But if you always want an English uppercase name, you can optionally call dow.toString() , which will also return FRIDAY as well.

  • This code focus only on the day of the week. If you need to use the date for other things than getting FRIDAY (like checking the day, month, etc), then you'll need a LocalDate and @JonSkeet's solution is preferred (and LocalDate has the method getDayOfWeek() , which returns the corresponding DayOfWeek , just in case you need it).

  • java.time is available only in Java >= 8. If you're using Java <= 7, though, you can use the ThreeTen Backport . The only difference is the package name ( org.threeten.bp instead of java.time ), but the classes and methods names are the same.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM