getDay()方法无法返回给定日期的星期几。

8
我正在尝试完成HackerRank上名为Java Date and Time的任务。
任务:
你会得到一个日期。你只需要编写getDay方法,返回该日期的星期几。例如,如果你得到的日期是2017年8月14日,那么该方法应该返回星期一。
我已经尽力完成了任务,但是我要么得到null结果,要么得到NullPointerException错误。我想知道我做错了什么。下面是我的代码:
提前感谢!
我的代码:
import java.util.*;

public class Solution {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String month = in.next();
        String day = in.next();
        String year = in.next();

        System.out.println(getDay(day, month, year));
    }

    public static String getDay(String day, String month, String year) {
        Calendar cal = Calendar.getInstance();
        cal.set(Integer.valueOf(year), (Integer.valueOf(month) - 1), Integer.valueOf(day));
        return cal.getDisplayName(cal.get(Calendar.DAY_OF_WEEK), Calendar.LONG, Locale.getDefault());
    }
}

4
LocalDate.of(2017, 8, 14).getDayOfWeek().toString() 的翻译是:MONDAY。 - Basil Bourque
4
除非你需要处理旧代码,否则学习过时的API可能是在浪费时间。 - assylias
@BasilBourque 这是Java 8,对吗? - Said
@assylias 我刚开始在HackerRank上挑战编程题。我是一个真正的新手,但我希望最终能成为一名优秀的竞技程序员。如果你有更好的建议,我会很乐意听取 :) - Said
3
java.time 类是嵌入在 Java 8 及之后的版本中的。它们的许多功能被移植到 ThreeTen-Backport 项目中,以支持 Java 6 和 7。因为旧的类非常混乱,所以将其添加到您的项目中是非常值得的。请搜索 Stack Overflow 了解更多信息,这个问题已经被多次解决过了。 - Basil Bourque
8个回答

12

你的return存在问题;在cal.getDisplayName的第一列中,你不需要使用cal.get。目前,你的代码返回的是月份名称。请将其更改为

return cal.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG, Locale.getDefault());

并且称其为

public static void main(String[] args) {
    System.out.println(getDay("14", "8", "2017"));
}

我得到了(如预期)

Monday

在新代码中,我更喜欢使用java.time(Java 8+)中的新类和类似于DateTimeFormatter的工具。

public static String getDay(String day, String month, String year) {
    int y = Integer.parseInt(year), m = Integer.parseInt(month), d = Integer.parseInt(day);
    return java.time.format.DateTimeFormatter.ofPattern("EEEE")
            .format(LocalDate.of(y, m, d));
}

真的有效,谢谢!顺便问两个问题:1. 在 cal.set(Integer.valueOf(year), (Integer.valueOf(month) - 1), Integer.valueOf(day)); 这行之后,Calendar.DAY_OF_WEEK 的值变成了_实际星期几_,而不是系统当前的日期,对吗?2. 如果我只想要一周中某天的整数值,使用 cal.get(Calendar.DAY_OF_WEEK) 来调用字符串会更好,就像这样:int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);(返回1-7之间的某个值)。 - Said
2
一:Calendar.DAY_OF_WEEK是一个static final常数7,它不会“变成实际星期几”,它从来没有改变过。它是一个常数。 二:看一下Calendar.SUNDAY,它是一个1。 三:优先使用java.time中的类而不是java.util.Calendar中的类。 - Elliott Frisch
1
另外,您可以调用.getDayOfWeek().getDisplayName而不是调用.format来自动本地化星期几的名称。 - Basil Bourque

3

java.time.LocalDate

现代方法使用 java.time 类。

  1. 导入java.time.*以访问 LocalDateDayOfWeek 类。
  2. 编写 getDay 方法,应该是静态的,因为它在主方法中被调用。
  3. 使用 "int" 格式的 3 个参数使用 of 方法检索 localDate。
  4. getDay 方法的参数转换为 int 格式。
  5. 最后使用 getDayOfWeek 方法检索那一天的名称。

这里有一个关于此挑战的视频。 Java 日期和时间 Hackerrank

LocalDate                 // Represent a date-only value, without time-of-day and without time zone.
.of( 2018 , 1 , 23 )      // Pass year-month-day, 1-12 for January-December. 
.getDayOfWeek()           // Obtain a `DayOfWeek` enum object.
.getDisplayName(          // Automatically localize the name of the day-of-week.
    TextStyle.FULL ,      // How long or abbreviated.
    Locale.US             // Or Locale.CANADA_FRENCH or so on.
)                         // Returns `String` such as `Monday` or `lundi`. 

针对Java 6和7版本,请参考ThreeTen-Backport项目。如果是更早期的Android版本,请查看ThreeTenABP项目。


3

如果您想使用 LocalDate,可以按照以下方式使用它

 import java.time.LocalDate;

 public static String getDay(int month, int day, int year) {

    return LocalDate.of(year, month, day).getDayOfWeek().name();

    }

感谢您的贡献。这确实是一个好建议,我认为它已经在其他答案中出现了(略有不同)。 - Ole V.V.

1
使用java.util日期和日历格式化日期和时间,如果需要在Java 7中处理异常,则需要使用java.text.SimpleDateFormat。
public static void main(String[] args){
    String inputDateStr = String.format("%s/%s/%s", 23, 04, 1995);
    Date inputDate = null;
    try {
        inputDate = new SimpleDateFormat("dd/MM/yyyy").parse(inputDateStr);
    } catch (ParseException ex) {
        Logger.getLogger(JavaApplication28.class.getName()).log(Level.SEVERE, null, ex);
    }
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(inputDate);
    String dayOfWeek = calendar.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG, Locale.US).toUpperCase();
    System.out.println(dayOfWeek);

}

使用Java 8中的java.time类格式化日期和时间,如下所示。它是不可变且线程安全的。
import java.time.LocalDateTime; 
import java.time.format.DateTimeFormatter; 

public class Main {
  public static void main(String[] args) {
    LocalDateTime dateObj = LocalDateTime.now();
    System.out.println("Before formatting: " + dateObj);
    DateTimeFormatter formatObj = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss");

    String formattedDate = dateObj.format(formatObj);
    System.out.println("After formatting: " + formattedDate);
  }
}

1
请注意,像java.util.Datejava.util.Calendarjava.text.SimpleDateFormat这样的旧日期时间类现在已经成为遗留系统,被内置于Java 8及更高版本中的java.time类所取代。请参阅Oracle的教程 - Basil Bourque

1

你可以使用新的Java8日期时间API。

public static String getDay(int day, int month, int year) 
{
    LocalDate dt=LocalDate.of(year, month, day);
    System.out.println("day: " + dt.getDayOfWeek().toString());
    return dt.getDayOfWeek().toString();
}

LocalDate 是一个没有时间的日期,非常适合我们的目的。 of 工厂方法构造了我们想要的日期。与问题中使用的 Calendar 类不同,它从 1 表示一月到 12 表示十二月,更加合理地编号月份。 LocalDate 有一个获取星期几的 getter。它返回一个常量,来自 DayOfWeek 枚举,其 toString 方法给出了一个漂亮易读的字符串,例如 MONDAY,这与我们从 Calendar 得到的结果形成对比。


3
虽然这段代码可能解决了问题,但是加入一个说明,解释这个代码如何以及为什么解决了问题,会大大提高您的帖子质量,并且可能会得到更多的赞同。请记住,你在回答这个问题不仅是为了当前提问者,也是为了未来的读者。请编辑你的回答并增加解释,同时指出其中的限制和假设。 - rizerphe

1
public static String findDay(int month, int day, int year) {
 Calendar cal = Calendar.getInstance();
    cal.set(year, (month - 1), day);
    String dayOfWeek = cal.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG, Locale.getDefault());
    return dayOfWeek.toUpperCase();
}

我建议你不要使用Calendar。那个类设计得很差,而且已经过时了。相反,你应该使用LocalDateDayOfWeek,它们都来自于Java时间和日期API(java.time) - Ole V.V.

1
    public static String getDay(int month, int day, int year) {
   String  res= java.time.format.DateTimeFormatter.ofPattern("EEEE")
        .format(java.time.LocalDate.of(year, month, day));
   return res;    }

如果您使用直接的LocalDate,会出现编译时错误,即无法找到符号,因此必须使用java.time.LocalDate。


您可以添加导入语句 import java.time.LocalDate;import java.time.format.DateTimeFormatter;,这样您就不需要在方法中使用 java.timejava.time.format 的限定符了。 - Ole V.V.
1
是的,你也可以这样做。 - PawanSinghla

0
public static String findDay(int month, int day, int year) {
     Calendar rightNow = Calendar.getInstance();
        rightNow.set(year, month-1, day);;
        switch(rightNow.get(Calendar.DAY_OF_WEEK)) {
            case Calendar.SUNDAY:
                return "SUNDAY";
            case Calendar.MONDAY:
                return "MONDAY";
            case Calendar.TUESDAY:
                return "TUEDAY";
            case Calendar.WEDNESDAY:
                return "WEDNESDAY";
            case Calendar.THURSDAY:
                return "THURSDAY";
            case Calendar.FRIDAY:
                return "FRIDAY";
            case Calendar.SATURDAY:
                return "SATURDAY";            
   
}

}


2
感谢您的贡献意愿。在某些方面,这个回答是不够好的。正如许多人已经指出的那样,没有人应该再使用笨重而过时的Calendar类了。这段代码太过手动,太过繁琐。与其他每一个回答中更简单、更短的代码相比较一下吧。而且,仅有代码的回答并不是很有用。我们都是通过解释来学习的。所以,在您的下一个回答中,请提供一些解释。 - Ole V.V.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接