2010-05-26 35 views
7

Tengo 2 objetos de fecha en la base de datos que representan las horas de trabajo de la empresa.¿Luchando con cómo comparar horas con diferentes zonas horarias en Java?

Solo necesito el horario, pero como tengo que guardar la fecha. Se parece a esto:

Date companyWorkStartHour; 
Date companyWorkEndHour; 

hora de inicio: 12-12-2001-13: 00: 00 horas acabado: 12-12-2001-18: 00: 00

tengo la zona horaria de la empresa y del usuario. (mi servidor puede estar en otra zona horaria).

TimeZone userTimeZone; 
TimeZone companyTimeZone; 

tengo que comprobar si el tiempo actual del usuario (teniendo en cuenta su zona horaria) está dentro del trabajo de la compañía horas (teniendo en cuenta la zona horaria de la empresa).

¿Cómo puedo hacerlo? ¡Estoy luchando durante más de una semana con el calendario de Java y sin éxito!

+0

¿Ya se ha tenido en cuenta la zona horaria del DB? ¿Las horas son correctas cuando lo consulta desde el DB como java.sql.Date e imprime de inmediato? – BalusC

+0

La recomendación general es almacenar todos los tiempos en UTC y solo convertir a otras zonas horarias y desde otras para la entrada y la presentación. Entonces la comparación debería ser directa. 'Date' y su reemplazo moderno' Instant' usan UTC internamente. –

Respuesta

6

La clase java.util.Date es un contenedor que contiene un número de milisegundos desde el 1 de enero de 1970, 00:00:00 UTC. Tenga en cuenta que la clase Date no sabe nada sobre husos horarios. Use la clase Calendar si necesita trabajar con zonas horarias. (edit 19-ene-2017: si usa Java 8, use la nueva API de fecha y hora en el paquete java.time).

La clase Date no es realmente adecuada para contener un número de hora (por ejemplo, 13:00 o 18:00) sin una fecha. Simplemente no está hecho para ese propósito, así que si intentas usarlo así, como pareces estar haciendo, te encontrarás con una serie de problemas y tu solución no será elegante.

Si se olvida sobre el uso de la clase Date para almacenar las horas de trabajo y sólo tiene que utilizar números enteros, esto será mucho más simple:

Date userDate = ...; 
TimeZone userTimeZone = ...; 

int companyWorkStartHour = 13; 
int companyWorkEndHour = 18; 

Calendar cal = Calendar.getInstance(); 
cal.setTime(userDate); 
cal.setTimeZone(userTimeZone); 

int hour = cal.get(Calendar.HOUR_OF_DAY); 
boolean withinCompanyHours = (hour >= companyWorkStartHour && hour < companyWorkEndHour); 

Si también quiere tomar minutos (no sólo horas) en cuenta, podría hacer algo como esto:

int companyWorkStart = 1300; 
int companyWorkEnd = 1830; 

int time = cal.get(Calendar.HOUR_OF_DAY) * 100 + cal.get(Calendar.MINUTE); 
boolean withinCompanyHours = (time >= companyWorkStart && time < companyWorkEnd); 
+0

Gracias! tu código me ayudó mucho. Otra pregunta relacionada: Necesito mostrar al usuario las horas de la compañía en la zona horaria del usuario. ¿Cómo puedo hacerlo si el companyWorkStartHour y el companyWorkEndHour son enteros? – Riki

+0

@Riki: Supongo que esas horas ya están en la zona horaria del usuario, ¿no es así? Puede crear un 'Calendario' y establecer la zona horaria en él como en mi código anterior, y puede establecer campos individuales en el' Calendario' con 'set()', por ejemplo: 'cal.set (Calendar.HOUR_OF_DAY, companyWorkStartHour); '. – Jesper

+0

Sí, ¡tienes razón! ¡hasta que me hayas respondido lo hice como tu sugerencia! – Riki

0

Oye, no estoy seguro de cómo harías esto usando el calendario de Java, pero te recomendaría usar el paquete Joda Time. Es un sistema mucho más simple de usar y te da métodos directos para extraer todos los subcomponentes de datos y tiempo e incluso solo para crear objetos de tiempo simples sin la fecha involucrada. Entonces me imagino que sería una cuestión de comparar las 2 diferencias de zona horaria y restar la diferencia del objeto JodaTime.

+2

Publique un ejemplo que responda a su pregunta, ¿entonces? Decir que JodaTime es mejor es fácil ya que es un hecho conocido, pero no tiene valor si ** no responde ** la pregunta. Publiquelo como un comentario entonces. – BalusC

0

No he probado la biblioteca Joda. Este código debería funcionar.

public boolean checkUserTimeZoneOverLaps(TimeZone companyTimeZone, 
     TimeZone userTimeZone, Date companyWorkStartHour, 
     Date companyWorkEndHour, Date userCurrentDate) { 

    Calendar userCurrentTime = Calendar.getInstance(userTimeZone); 
    userCurrentTime.setTime(userCurrentDate); 
    int year = userCurrentTime.get(Calendar.YEAR); 
    int month = userCurrentTime.get(Calendar.MONTH); 
    int day = userCurrentTime.get(Calendar.DAY_OF_MONTH); 

    Calendar startTime = Calendar.getInstance(companyTimeZone); 
    startTime.setTime(companyWorkStartHour); 
    startTime.set(Calendar.YEAR, year); 
    startTime.set(Calendar.MONTH, month); 
    startTime.set(Calendar.DAY_OF_MONTH, day); 

    Calendar endTime = Calendar.getInstance(companyTimeZone); 
    endTime.setTime(companyWorkEndHour); 
    endTime.set(Calendar.YEAR, year); 
    endTime.set(Calendar.MONTH, month); 
    endTime.set(Calendar.DAY_OF_MONTH, day); 

    if (userCurrentTime.after(startTime) && userCurrentTime.before(endTime)) { 
     return true; 
    } 
    return false; 
} 

EDITAR Actualizado el código para reflejar los comentarios de Bruno. No debería tomarse las fechas de los horarios de trabajo de la empresa.

+0

Snehal, el problema es que está utilizando las horas de inicio/finalización con la parte de la fecha en la que se guardaron (por ejemplo, 12-12-2001). Por lo tanto, puede estar comparando la fecha de hoy (de 'userCurrentDate') al 12-12-2001 (de' companyWorkStart/EndHour'). –

+0

¿Pero no sería falso, en caso de que eso suceda? – Snehal

+0

Sí. Pero la parte de la fecha no debe tenerse en cuenta en la comparación en este caso. Está interesado en verificar si la hora actual del usuario se encuentra entre el horario de inicio y el de finalización del trabajo, por lo que solo importa la parte de tiempo de las fechas guardadas de empresa/inicio/final de estancia. –

2

intentar algo como esto:

Calendar companyWorkStart = new GregorianCalendar(companyTimeZone); 
companyWorkStart.setTime(companyWorkStartHour); 

Calendar companyWorkEnd = new GregorianCalendar(companyTimeZone); 
companyWorkEnd.setTime(companyWorkEndHour); 

Calendar user = new GregorianCalendar(userTimeZone); 
user.setTime(userTime); 

if(user.compareTo(companyWorkStart)>=0 && user.compareTo(companyWorkEnd)<=0) { 
    ... 
} 
Cuestiones relacionadas