Bug al obtener una semana con java?

Que tal amigos, buen día a todos ud.

Me encuentro en una situación un poco rara, estoy ocupando una variable de tipo GregorianCalendar (private Calendar c = new GregorianCalendar(); ) para obtener la semana actual pero me sale una ¿incorrecta?.

Que es lo que sucede?
Bueno resulta que la ultima semana del año anterior por ahí de los días 29 de dic. al obtener la semana me daba 1, cuando se supone que debería ser 53 por lo tanto google un poco y encontré un sitio que explican algo sobre esto, tmb leí la documentación que ofrece oracle donde nos indica que la semana debe de tener al menos 4 días para que se tome como una semana.... pero... se supone que la ultima semana de dic cuenta con 6 días, el 1ro de enero fue sábado, por lo tanto debería ser aun semana 53??

La vdd me encuentro un tanto confundido y quisiera saber si alguien pudiera explicarme un poco mas sobre esto.

Gracias y saludos.

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

JodaTime

Si haces la prueba con JodaTime qué te sale?

Un medio bug:

Así sale 1 como dices:

Calendar c = Calendar.getInstance();
c.setTime( new SimpleDateFormat("dd/MM/yyyy").parse("29/12/2010"));
System.out.println( c.get( Calendar.WEEK_OF_YEAR ) ); // prints 1

No es un bug en sentido estricto, por que está bien identificado y documentado por Sun Oracle. Lo que sí es verdad es que está medio revuelto y tiene que ver con la definición de cuantos días del año se necesitan para decir que ya empezó la primera semana.

Por default tiene 1, es decir, se necesita 1 día para decir "esta es la primera semana del año"

Ejemplo:

import java.util.Calendar;
import java.text.*;
import static java.lang.System.out;

public class WeekOfYear {
        public static void main( String [] args ) throws ParseException {  
       
                Calendar c = Calendar.getInstance();
                DateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");

                c.setTime( sdf.parse("31/12/2010"));
                out.println( c.get( Calendar.WEEK_OF_YEAR ) );  // imprime 1

                c.setTime( sdf.parse("01/01/2011"));
                out.println( c.get( Calendar.WEEK_OF_YEAR ) ); // 1 por que  ya empezo la primera semana del año

        }
}

El "chiste" está en entender getMinimalDaysInFirstWeek()
Por default tiene 1,
O sea que el sabado 1 y el domingo 2 de enero hacen que la semana del: [lunes 27-dic-10] al [dom. 02-ene-11] ya sea la 1ra semana del año ( pero del 2011 )

Si aumentamos este valor de getMinimalDaysInFirstWeek(), para necesitar al menos 3 días como mínimo, ya sale 53 como esperas:

c.setMinimalDaysInFirstWeek( 3 );
out.println( c.get( Calendar.WEEK_OF_YEAR ) ); // imprime 53

Pero en realidad ningun año tiene 53 semanas todos tienen 52.14 o algo asi
entonces 53 tampoco del todo correcto.

Todos los 1ros de enero y 31's de diciembre pertenecen siempre a la misma semana la cuestión está en decidir si es la primera o la ultima del año.

Con este cambio al intentar:

c.setTime( sdf.parse("02/01/2011"));
out.println( c.get( Calendar.WEEK_OF_YEAR ) );

También imprime 53.

A mi me parece lo mejor como lo hizo la persona del blog que citas:

if (month == Calendar.DECEMBER && week == 1) {
year++;
}

Luego no es un bug del todo,pero si entra en conflicto con lo que nos dice el sentido común, donde esperaríamos que el 31 de dic, siempre va a ser una semana del año. Pero siendo congruentes, el 31 de dic, no es una semana del año, por que no termina en domingo.

Uff, bueno espero que se aclaro un poco el punto. Esperamos tu salida de usar Joda ( que estoy casi seguro saldrá lo mismo )

Imagen de AlexSnake

Obtener sem.

Hola ezamudio gracias por tu resp, mmmmm no he probado con JodaTime investigare un poco al respecto, a ver que sale.
Que tal OscarRyz claro que sí, mira este es el código que ocupo para obtener la sem:

Calendar c = new GregorianCalendar();
c.get(Calendar.WEEK_OF_YEAR)

Sobre como sale en Joda

Es exactamente lo mismo, entonces lo declaro como no bug :)

http://joda-time.sourceforge.net/field.html#weekOfWeekyear

...Since all weeks start on Monday, the first week of 2003 started on 2002-12-30, ie. in 2002...

El 30 de diciembre del 2002 sería también representado como la primera semana del 2003:

2002-12-30 (Monday 30th December 2002) would be represented as 2003-W01-1.
2003-01-01 (Wednesday 1st January 2003) would be represented as 2003-W01-3.

Que es identico a como lo hace java.util.Calendar. ¿No es genial Google?

Imagen de AlexSnake

Oks.

Excelente explicación, no has pensado impartir clases?? serias un buen profesor. Exactamente estaba revisando lo de Joda no mas que soy un poco mas lento :P. Bueno pues entonces caso cerrado.
Muchas gracias Oscar, Saludos.

Imagen de bferro

You can't escape time. Why not make it easy?

El artículo "Joda-Time: You can't escape time. Why not make it easy?" en http://www.ibm.com/developerworks/java/library/j-jodatime.html explica muy bien ls ventajas de Joda Time para el manejo de fechas, horas, etc.

Definitivamente la interfaz

Definitivamente la interfaz de java.util.Calendar esta muy mal diseñada y resulta extremadamente complicado y engorroso escribir con ella. Joda lo hace mucho más fácil.

Pero el que sea difícil de usar no implica que haga las cosas mal. Simplemente es feita. En este caso, ambos ( java.util.Calendar y Joda time ) devuelven el mismo resultado.

+1 por el artículo

Imagen de Mike060987

SALUDOS A TODOS

RETOMANDO EL TEMA DE ALEX
TENGO UN TEMA DESDE HACE TIEMPO QUE NO EH PODIDO RESOLVER Y PIDO DE SU AYUDA PARA PODER LOGRARLO

DADA LA SEMANA DEL AÑO CUAL SEA ESTOY INTERESADO EN OBTENER QUE SEMANA DEL MES ES YA SEA SEMANA 1, 2, 3, 4 O ALGUNOS MESES 5 Y LAS FECHAS QUE LA CONFORMAN POR EJEMPLO

LA SEMANA 36 DEL AÑO EN CURSO QUE ES LA SEMANA 1 DE SEPTIEMBRE
EL RESULTADO QUE ME DARIA ES
FECHA INICIAL
1-09-2014 A 7-09-2014

TOMANDO LA NORMA ISO-8601
QUE LA SEMANAS COMIENZAN EL LUNES
ESTE OTRO EJEMPLO LA SEMANA 1 DEL 2014
ES 30-12-2013 A 5-01-2014

DE ANTEMANO GRACIAS

Lee el "javadoc" :)

 

Si lees un poco el javadoc, puedes fácilmente encontrar que:

Java

import java.util.Calendar;

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

    Calendar c = Calendar.getInstance();
    c.setFirstDayOfWeek(Calendar.MONDAY);
    c.setMinimalDaysInFirstWeek(1);

    c.clear();
    c.set(Calendar.YEAR, 2014);
    c.set(Calendar.WEEK_OF_YEAR, 1);
    System.out.printf("Fecha del Lunes: %te-%<tm-%<ty%n", c.getTime());
    System.out.printf("Semana del mes (%tB %<tY): %d%n", c.getTime(), c.get(Calendar.WEEK_OF_MONTH));
    c.add(Calendar.DAY_OF_YEAR, 6);
    System.out.printf("Fecha del Domingo: %te-%<tm-%<ty%n", c.getTime());
    System.out.printf("Semana del mes (%tB %<tY): %d%n", c.getTime(), c.get(Calendar.WEEK_OF_MONTH));

    System.out.println();

    c.clear();
    c.set(Calendar.YEAR, 2014);
    c.set(Calendar.WEEK_OF_YEAR, 36);
    System.out.printf("Fecha del Lunes: %te-%<tm-%<ty%n", c.getTime());
    System.out.printf("Semana del mes (%tB %<tY): %d%n", c.getTime(), c.get(Calendar.WEEK_OF_MONTH));
    c.add(Calendar.DAY_OF_YEAR, 6);
    System.out.printf("Fecha del Domingo: %te-%<tm-%<ty%n", c.getTime());
    System.out.printf("Semana del mes (%tB %<tY): %d%n", c.getTime(), c.get(Calendar.WEEK_OF_MONTH));

  }
}

Salida

Fecha del Lunes: 30-12-13
Semana del mes (diciembre 2013): 6
Fecha del Domingo: 5-01-14
Semana del mes (enero 2014): 1

Fecha del Lunes: 1-09-14
Semana del mes (septiembre 2014): 1
Fecha del Domingo: 7-09-14
Semana del mes (septiembre 2014): 1

;)

~~~