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