一个非常简单的java代码(获取一周工作日的日期),但我得到了非常奇怪的结果,为什么?

时间:2010-10-16 14:18:51

标签: java datetime

我有以下java代码来获取特定工作日的日期:

SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
Calendar cal = Calendar.getInstance();
cal.setTime(new Date());
cal.set(Calendar.YEAR, 2010);
cal.set(Calendar.WEEK_OF_YEAR, 37); //week 37 of year 2010
cal.set(Calendar.DAY_OF_WEEK, Calendar.THURSDAY);
System.out.println("date="+sdf.format(cal.getTime()));

当我将此代码放入main(String[] args)方法时,如下所示:

import java.util.*;
import java.lang.*;
import java.text.SimpleDateFormat;

public class test{
    public static void main(String[] args){

    /** get dates from a known week ID **/
    SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
    Calendar cal = Calendar.getInstance();
    cal.setTime(new Date());
    cal.set(Calendar.YEAR, 2010);
    cal.set(Calendar.WEEK_OF_YEAR, 37);
    cal.set(Calendar.DAY_OF_WEEK, Calendar.THURSDAY);
    System.out.println("date="+sdf.format(cal.getTime()));
    }
}

并运行它,我得到正确的结果date=09/09/2010。没问题。

无论其...

当我将此代码放在Class的函数中时,如下所示:

Public Class MyService{

  MyService(){}
  ...
  ...
  public String getDateOfWeekDay(int weekId, int year, int weekDay){
      //weekId = 37; year=2010; weekDay = Calendar.THURSDAY

      SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
      Calendar cal = Calendar.getInstance();
      cal.setTime(new Date());
      cal.set(Calendar.YEAR, year);
      cal.set(Calendar.WEEK_OF_YEAR, weekId);
      cal.set(Calendar.DAY_OF_WEEK, weekDay);

      //I am developing android app. so I use Log to printout
      logPrinter.println("date="+sdf.format(cal.getTime())); 

      return  sdf.format(cal.getTime());    
  }

}

在另一个类MainClass中,MainClass将调用此服务函数,如下所示:

Public Class MainClass{

MyService myService = new MyService();
myService.getDateOfWeekDay(37,2010,Calendar.THURSDAY);

}

但返回的结果始终是当前周的星期四(日期= 2010年10月14日)的日期,而不是我指定的周的星期四(第37周,2010年,星期四) )。 为什么????我使用完全相同的java代码来获取特定工作日的日期,只是以不同的方式使用它,为什么结果不同????我无法理解这一点......有人可以向我解释一下吗?

4 个答案:

答案 0 :(得分:4)

是的,JodaTime很精彩,但我敢打赌,你宁愿知道你的东西有什么问题。

添加另一个JAR依赖项可能是移动设备的问题。

这种方法不好,IMO。这个名字用词不当,它做的事情太多了。您正在创建一个字符串,而不是日期,并且您正在打印到日志。我建议返回一个Date,让客户担心他们是否想把它变成一个String。记录是一个贯穿各领域的问题。

这是一个有效的类(和JUnit测试)。看看有什么不同:

package util;

import java.util.Calendar;
import java.util.Date;

public class DateUtils
{
    public static Date getDateOfWeekDay(int weekId, int year, int weekDay)
    {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.WEEK_OF_YEAR, weekId);
        cal.set(Calendar.DAY_OF_WEEK, weekDay);
        cal.set(Calendar.HOUR, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);

        return cal.getTime();
    }

}

JUnit测试:

package util;

import org.junit.Assert;
import org.junit.Test;

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

/**
 * DateUtilsTest
 * User: Michael
 * Date: 10/16/10
 * Time: 10:40 AM
 */
public class DateUtilsTest
{
    public static final DateFormat DEFAULT_FORMAT = new SimpleDateFormat("dd/MM/yyyy");

    @Test
    public void testNewYearsDayLastYear() throws ParseException
    {
        Date expected = DEFAULT_FORMAT.parse("1/1/2009");
        Date actual = DateUtils.getDateOfWeekDay(1, 2009, Calendar.THURSDAY);

        Assert.assertEquals(expected, actual);
    }

    @Test
    public void testTaxDay() throws ParseException
    {
        Date expected = DEFAULT_FORMAT.parse("15/4/2010");
        Date actual = DateUtils.getDateOfWeekDay(16, 2010, Calendar.THURSDAY);

        Assert.assertEquals(expected, actual);
    }

    @Test
    public void testGetDateOfWeekDay() throws ParseException
    {
        Date expected = DEFAULT_FORMAT.parse("16/10/2010");
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(expected);
        int week = calendar.get(Calendar.WEEK_OF_YEAR);
        int year = calendar.get(Calendar.YEAR);
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);

        Date actual = DateUtils.getDateOfWeekDay(week, year, dayOfWeek);

        Assert.assertEquals(expected, actual);
    }
}

答案 1 :(得分:3)

这是一个死记硬背的答案,但是:使用JodaTime或其中一个替代方案。投入宝贵的周期来理解JDK日历API在糟糕的情况下投入了大量资金。

与SO相关:Should I use native date/time;我看到(现在)你正在进行Android开发,我无法与之交谈,但在SO:JodaTime on Android?

如果您坚持使用JDK,我会尝试您的代码,稍作修改。首先,我要消除cal.setTime(new Date()) - 它没有做任何事情,而且它很混乱,因为它可能(似乎)与始终获得“现在”的约会相关,因为new Date()现在给你。但是,在您的代码中,它仍然应该被以下setX调用覆盖。

class DateTest
{
    DateTest(){}

    public String getDateOfWeekDay(int weekId, int year, int weekDay){

        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.WEEK_OF_YEAR, weekId);
        cal.set(Calendar.DAY_OF_WEEK, weekDay);

        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
        System.out.println("date="+sdf.format(cal.getTime())); 

        return  sdf.format(cal.getTime());    
    }

    public static void main(String args[])
    {
      DateTest dt = new DateTest();
      for (int weekCount = 1; weekCount <= 53; weekCount++) {
        dt.getDateOfWeekDay(weekCount,2010,Calendar.THURSDAY);
      }
    }

}

我完全得到了我的期望:

date=31/12/2009 
date=07/01/2010 
...
date=23/12/2010 
date=30/12/2010

你看到不同吗?

答案 2 :(得分:1)

public class CalendarTest {

    public static String getDateOfWeekDay(int weekId, int year, int weekDay) {
        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date());
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.WEEK_OF_YEAR, weekId);
        cal.set(Calendar.DAY_OF_WEEK, weekDay);
        return sdf.format(cal.getTime());
    }

    public static void main(String[] args) {
        String someDay = getDateOfWeekDay(37,2010,Calendar.THURSDAY);
        System.out.println(someDay);
    }

}

输出   16/09/2010

public class CalendarTest {
    public static void main(String[] args) {
        MyService s = new MyService();
        String someDay = s.getDateOfWeekDay(37, 2010, Calendar.THURSDAY);
        System.out.println(someDay);
    }
}

class MyService {
    public String getDateOfWeekDay(int weekId, int year, int weekDay) {
        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date());
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.WEEK_OF_YEAR, weekId);
        cal.set(Calendar.DAY_OF_WEEK, weekDay);
        return sdf.format(cal.getTime());
    }
}

答案 3 :(得分:0)

好吧,因为这些答案不是回答你的实际问题,而是建议使用JodaTime,我会推荐反对 JodaTime。

日期/日历以及JodaTime存在重大设计缺陷(引用作者),如果您计划使用时间和日期,请使用JSR-310

JSR-310是Date / Calendar和JodaTime的替代品,它更加一致并且比两者都更好。需要考虑的问题包括JSR-310 in Java 7

无论是否有效,今天都可以使用它。它只是一个像JodaTime这样的jar文件。

好处是:

  • 修复了JodaTime的剩余问题
  • 一致的图书馆设计
  • 更好的命名惯例
  • 更易于阅读API
  • 一切不可改变
  • 其他编程语言的可用性更高

如果您对此主题感兴趣: