Obtenir le numéro de la semaine et l’année en Java

Obtenir le numéro de semaine est parfois bien difficile et il existe de nombreux pièges à éviter.

Par exemple, il faut savoir le 1er Janvier n’est pas toujours la première semaine de l’année. Elle peux être la dernière semaine de l’année précédente. C’est le principe inversé pour le 31 Décembre.

De plus, certains calendriers (américain notamment) commencent leur semaine le Dimanche, ce qui peut provoquer des anomalies dans la comparaison avec un calendrier Français. Pire, le même programme peut parfois retourner 2 numéros de semaines différents pour la même car il prend en compte le calendrier système de la machine.

Pour éviter tout ces problèmes, il existe une norme qui permet de mettre tout le monde d’accord. Il s’agit de la norme  ISO sur la numérotation des semaines.

Pour simplifier, la première semaine de l’année est la semaine avec le premier jeudi de l’année, ou la première semaine ayant au moins 4 jours

Quelques exemples :

  • 01/01/2010 est la 53ième semaine de l’année 2009
  • 31/12/2010 est la 52ième semaine de l’année 2010
  • 01/01/2011 est la 52ième semaine de l’année 2010
  • 01/01/2012 est la 52ième semaine de l’année 2011
  • 31/12/2012 est la 1ière semaine de l’année 2013
  • 01/01/2013 est la 1ière semaine de l’année 2013

Pour information, MySql propose une fonction native permettant de récupérer cette information sous la forme YYYYWW (ou WW est le numéro de la semaine), c’est la fonction YEARWEEK(date,3) ou 3 désigne le mode correspondant à la norme ISO. Plus d’infos sur la page des dates de MySQL.

Voici l’exemple d’un code permettant d’avoir le numéro de la semaine et l’année en en Java.
Cette fonction retourne le numéro de la semaine et l’année sous la forme YYY/WW
package com.alcatellucent.gmot.core.utils;

import java.text.DecimalFormat;
import java.util.Calendar;
import java.util.Date;

public class DateWeekYear {
	public static String yearWeekYearFromDate(Date date) {
		Calendar cal = Calendar.getInstance();
		//La première semaine de l'année est celle contenant au moins 4 jours
		cal.setMinimalDaysInFirstWeek(4);
		cal.setTime(date);
		//On récupère le numéro de la semaine
		int week = cal.get(Calendar.WEEK_OF_YEAR);
		int annee;
		//On récupère l'année du premier jour de cette semaine
		if (week >= 52) {
			cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
			annee = cal.get(Calendar.YEAR);
		} else if (week == 1) {
			cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
			annee = cal.get(Calendar.YEAR);
		} else {
			annee = cal.get(Calendar.YEAR);
		}
		DecimalFormat df = new DecimalFormat("00");
		return annee + "/" + df.format(week);
	}
}

Et voici le test unitaire qui vérifie les différents cas précédemment cités

package fr.w3blog.junit;

import java.util.Calendar;

import junit.framework.TestCase;

import org.junit.Before;
import org.junit.Test;

import com.alcatellucent.gmot.core.exception.ProductCodeException;
import com.alcatellucent.gmot.core.utils.DateWeekYear;

/**
 * @author thibaut
 *
 */
public class TestYearWeekYear extends TestCase {

	/**
	 *
	 */
	@Before
	public void setUp() {
	}

	/**
	 * Test Numéro de semaine et année
	 *
	 * @throws ProductCodeException
	 *             ProductCodeException
	 *
	 */
	@Test
	public void testYearWeekYear() throws ProductCodeException {

		Calendar cal = Calendar.getInstance();

		cal.set(Calendar.DAY_OF_MONTH, 1);
		cal.set(Calendar.MONTH, 0);
		cal.set(Calendar.YEAR, 2010);
		assertEquals(DateWeekYear.yearWeekYearFromDate(cal.getTime()), "2009/53");

		cal.set(Calendar.DAY_OF_MONTH, 31);
		cal.set(Calendar.MONTH, 11);
		cal.set(Calendar.YEAR, 2010);
		assertEquals(DateWeekYear.yearWeekYearFromDate(cal.getTime()), "2010/52");

		cal.set(Calendar.DAY_OF_MONTH, 1);
		cal.set(Calendar.MONTH, 0);
		cal.set(Calendar.YEAR, 2011);
		assertEquals(DateWeekYear.yearWeekYearFromDate(cal.getTime()), "2010/52");

		cal.set(Calendar.DAY_OF_MONTH, 1);
		cal.set(Calendar.MONTH, 0);
		cal.set(Calendar.YEAR, 2012);

		assertEquals(DateWeekYear.yearWeekYearFromDate(cal.getTime()), "2011/52");

		cal.set(Calendar.DAY_OF_MONTH, 31);
		cal.set(Calendar.MONTH, 11);
		cal.set(Calendar.YEAR, 2012);
		assertEquals(DateWeekYear.yearWeekYearFromDate(cal.getTime()), "2013/01");

	}
}

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *