Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A very simple java code (to get date of a week day), but Very Strange result I get, WHY?

Tags:

java

datetime

I have the following java code to get the date of a specific week day:

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()));

When I put this code in a main(String[] args)method, like the following:

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()));
    }
}

and run it, I get the correct result which is date=09/09/2010. There is no problem.

HOWEVER...

When I put this code in a function of a Class, like the following:

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());    
  }

}

in another class MainClass, MainClass will invoke this service function like following:

Public Class MainClass{

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

}

But the result returned is always the date of the current week's thursday (date=14/10/2010), not the Thursday of the week which I specified (week 37, year 2010, Thursday). WHY???? I use exactly the same java code to get the date of the specific week day, only used it in different ways, why the result is different???? I can not understand this...Anybody can explain to me??

like image 285
Mellon Avatar asked Feb 26 '23 01:02

Mellon


2 Answers

Yes, JodaTime is wonderful, but I'll bet you'd rather know what's wrong with your stuff.

Adding another JAR dependency might be a problem for a mobile device.

That method isn't good, IMO. The name is a misnomer, and it's doing too many things. You're creating a String, not a Date, and you're printing to a log. I'd recommend returning a Date and let clients worry about whether they want to turn it into a String. Logging is a cross-cutting concern.

Here's a class (and a JUnit test) that works. See what's different:

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 test:

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);
    }
}
like image 131
duffymo Avatar answered Mar 29 '23 22:03

duffymo


It's becoming a rote answer around here, but: Use JodaTime or one of the alternatives. Investing precious cycles into understanding the JDK calendar API is throwing good money after bad.

Related on SO: Should I use native date/time; I see (now) you're doing Android development, which I can't speak to, but on SO: JodaTime on Android?

If you're insisting on JDK, I did try your code, with a slight modification. First, I'd eliminate the cal.setTime(new Date()) -- it's not doing anything, and it's confusing since it might (seem to) correlate to always getting a date around "now," since new Date() gives you now. However, in your code, it still should be overridden by the following setX calls.

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);
      }
    }

}

And I get exactly what I expect:

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

Do you see different?

like image 39
andersoj Avatar answered Mar 29 '23 22:03

andersoj