Tengo un valor de marca de tiempo que viene de mi aplicación. El usuario puede estar en cualquier zona Horaria local.

Desde esta fecha se utiliza para un WebService que supone que el tiempo siempre está en GMT, tengo necesidad de convertir el usuario el parámetro de decir (EST) (GMT). Aquí viene lo bueno: El usuario es totalmente ajeno a su TZ. Entra a la fecha de creación, que él quiere enviar a la WS, así que lo que necesito es:

Usuario entra en: 5/1/2008 6:12 PM (EST)

El parámetro para el WS necesita ser: 5/1/2008 6:12 PM (GMT)

Sé que hora son siempre supone GMT por defecto, pero al enviar el parámetro, aunque he creado mi Calendario a partir de la TS (que se supone que está en GMT), los horarios son siempre apagado a menos que el usuario está en GMT. Lo que me estoy perdiendo?

Timestamp issuedDate = (Timestamp) getACPValue(inputs_, "issuedDate");
Calendar issueDate = convertTimestampToJavaCalendar(issuedDate);
...
private static java.util.Calendar convertTimestampToJavaCalendar(Timestamp ts_) {
  java.util.Calendar cal = java.util.Calendar.getInstance(
      GMT_TIMEZONE, EN_US_LOCALE);
  cal.setTimeInMillis(ts_.getTime());
  return cal;
}

Con el Código anterior, esto es lo que obtengo como resultado (Formato Corto para facilitar la lectura):

[1 de mayo de 2008 11:12 PM]

  • ¿Por qué son sólo para cambiar la zona horaria y no convertir la fecha y la hora junto con él?
  • Es un verdadero dolor de cabeza para tomar un Java fecha en la que se encuentra en una zona horaria, y conseguir que la fecha en la otra zona. Es decir, tomar las 5PM EDT y obtener las 5 pm PDT.
InformationsquelleAutor Jorge Valois | 2008-10-23

9 Comentarios

  1. 61
    public static Calendar convertToGmt(Calendar cal) {
    
        Date date = cal.getTime();
        TimeZone tz = cal.getTimeZone();
    
        log.debug("input calendar has date [" + date + "]");
    
        //Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT 
        long msFromEpochGmt = date.getTime();
    
        //gives you the current offset in ms from GMT at the current date
        int offsetFromUTC = tz.getOffset(msFromEpochGmt);
        log.debug("offset is " + offsetFromUTC);
    
        //create a new calendar in GMT timezone, set to this date and add the offset
        Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
        gmtCal.setTime(date);
        gmtCal.add(Calendar.MILLISECOND, offsetFromUTC);
    
        log.debug("Created GMT cal with date [" + gmtCal.getTime() + "]");
    
        return gmtCal;
    }

    Aquí está la salida si me pase de la hora actual («12:09:05 EDT» de Calendar.getInstance()) en:

    De DEPURACIÓN de entrada de calendario de fecha [Jue 23 Oct 12:09:05 EDT 2008]

    DEBUG – offset es -14400000

    DEBUG – Creado GMT cal con fecha [Jue Oct 23 08:09:05 EDT 2008]

    12:09:05 GMT es de las 8:09:05 EDT.

    La parte confusa aquí es que Calendar.getTime() devuelve un Date en su zona horaria actual, y también que no hay ningún método para modificar la zona horaria de un calendario y la fecha subyacente rodó también. Dependiendo de qué tipo de parámetro de su web de servicio de toma, puede que sólo quieren tener la WS oferta en términos de milisegundos desde la época de.

    • ¿No deberías estar restando offsetFromUTC en lugar de agregar? Usando tu ejemplo, si a las 12:09 GMT es de las 8:09 EDT (lo cual es cierto), y el usuario introduce «12:09 EDT», el algoritmo debe de salida «16:09 GMT», en mi opinión.
  2. 29

    Gracias a todos por responder. Después de una investigación más a fondo he llegado a la respuesta correcta. Como se ha mencionado por Saltar de la Cabeza, los sellos de tiempo que yo estaba recibiendo de mi solicitud se ajustan a la zona Horaria del usuario. Así que si el Usuario entró en 6:12 PM (EST) me gustaría conseguir 2:12 PM (GMT). Lo que yo necesitaba era una manera de deshacer la conversión para que el tiempo introducido por el usuario es el tiempo que he enviado al servidor Web de solicitud. He aquí cómo he logrado esto:

    //Get TimeZone of user
    TimeZone currentTimeZone = sc_.getTimeZone();
    Calendar currentDt = new GregorianCalendar(currentTimeZone, EN_US_LOCALE);
    //Get the Offset from GMT taking DST into account
    int gmtOffset = currentTimeZone.getOffset(
        currentDt.get(Calendar.ERA), 
        currentDt.get(Calendar.YEAR), 
        currentDt.get(Calendar.MONTH), 
        currentDt.get(Calendar.DAY_OF_MONTH), 
        currentDt.get(Calendar.DAY_OF_WEEK), 
        currentDt.get(Calendar.MILLISECOND));
    //convert to hours
    gmtOffset = gmtOffset / (60*60*1000);
    System.out.println("Current User's TimeZone: " + currentTimeZone.getID());
    System.out.println("Current Offset from GMT (in hrs):" + gmtOffset);
    //Get TS from User Input
    Timestamp issuedDate = (Timestamp) getACPValue(inputs_, "issuedDate");
    System.out.println("TS from ACP: " + issuedDate);
    //Set TS into Calendar
    Calendar issueDate = convertTimestampToJavaCalendar(issuedDate);
    //Adjust for GMT (note the offset negation)
    issueDate.add(Calendar.HOUR_OF_DAY, -gmtOffset);
    System.out.println("Calendar Date converted from TS using GMT and US_EN Locale: "
        + DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT)
        .format(issueDate.getTime()));

    El código de salida es: (introducidos por el Usuario 5/1/2008 6:12 PM (EST)

    Actual de la zona Horaria del Usuario: EST

    Corriente de Desplazamiento de GMT (en horas):-4 (Normalmente -5, excepto que es DST ajustado)

    TS de la ACP: 2008-05-01 14:12:00.0

    Calendario la Fecha convertida a partir de TS mediante GMT y US_EN configuración Regional: 5/1/08 6:12 PM (GMT)

  3. 20

    Que decir que la fecha se utiliza en conexión con los servicios web, así que supongo que se serializa en una cadena en algún momento.

    Si este es el caso, usted debe echar un vistazo a la setTimeZone método de la clase DateFormat. Esto nos indica que la zona horaria que será el utilizado para imprimir el sello de tiempo.

    Un ejemplo sencillo:

    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
    formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
    
    Calendar cal = Calendar.getInstance();
    String timestamp = formatter.format(cal.getTime());
    • No relise SDF Tenía su propia zona horaria, preguntándose por qué el cambio de Calendario de la zona Horaria parece no tener efecto!
    • La zona horaria.getTimeZone(«UTC») no es válido, ya UTC no es en AvailableIDs() … dios sabe por qué
    • La zona horaria.getTimeZone(«UTC») está disponible en mi máquina. Es dependiente de la JVM?
    • Impresionante idea con la setTimeZone() método. Usted me salvó un montón de dolores de cabeza, muchas gracias !
    • Justo lo que necesitaba! Usted puede configurar la zona horaria del servidor en el formateador y, a continuación, cuando se convierte a formato de calendario que no tienen nada de que preocuparse. Método que sea el mejor por lejos! para getTimeZone usted puede ser que necesite utilizar el formato Ex: «GMT-4:00» para el ETD
  4. 12

    Se puede resolver con Joda Tiempo:

    Date utcDate = new Date(timezoneFrom.convertLocalToUTC(date.getTime(), false));
    Date localDate = new Date(timezoneTo.convertUTCToLocal(utcDate.getTime()));

    Java 8:

    LocalDateTime localDateTime = LocalDateTime.parse("2007-12-03T10:15:30");
    ZonedDateTime fromDateTime = localDateTime.atZone(
        ZoneId.of("America/Toronto"));
    ZonedDateTime toDateTime = fromDateTime.withZoneSameInstant(
        ZoneId.of("Canada/Newfoundland"));
    • cuidado para esto, sin embargo, si usted está usando hibernate 4, que no es directamente compatible sin la dependencia y la extra de configuración. Sin embargo, era la forma más rápida y más fácil de usar enfoque para la versión 3.
  5. 8

    Parece que su marca de tiempo se establece para la zona horaria de origen del sistema.

    Este está en desuso, pero se debe trabajar:

    cal.setTimeInMillis(ts_.getTime() - ts_.getTimezoneOffset());

    La no-deprecated forma es utilizar

    Calendar.get(Calendar.ZONE_OFFSET) + Calendar.get(Calendar.DST_OFFSET)) / (60 * 1000)

    pero que tendrían que hacer en el lado del cliente, ya que el sistema sabe qué zona horaria en que se encuentra.

  6. 7

    Método para la conversión de una zona horaria a otra(probablemente funciona 🙂 ).

    /**
     * Adapt calendar to client time zone.
     * @param calendar - adapting calendar
     * @param timeZone - client time zone
     * @return adapt calendar to client time zone
     */
    public static Calendar convertCalendar(final Calendar calendar, final TimeZone timeZone) {
        Calendar ret = new GregorianCalendar(timeZone);
        ret.setTimeInMillis(calendar.getTimeInMillis() +
                timeZone.getOffset(calendar.getTimeInMillis()) -
                TimeZone.getDefault().getOffset(calendar.getTimeInMillis()));
        ret.getTime();
        return ret;
    }
  7. 6

    Fecha y Timestamp objetos de zona horaria-ajeno: que representan un cierto número de segundos desde la época, sin comprometerse a una particular interpretación de ese instante como horas y días.
    Zonas horarias entrar en la imagen sólo en GregorianCalendar (no directamente necesarios para esta tarea) y SimpleDateFormat, que necesitan de un ajuste de zona horaria para convertir entre distintos campos y Fecha (o largo) valores.

    El OP del problema es la derecha en el comienzo de su procesamiento: el usuario introduce horas, que son ambiguas, y se interpretan en el local, no zona horaria GMT; en este punto el valor es «6:12 EST», que puede ser fácilmente impreso como «11.12 GMT» o cualquier otra zona horaria, pero es que nunca va a cambio a «6.12 GMT».

    No hay manera de hacer que el SimpleDateFormat que analiza «06:12» como «HH:MM» (impago a la zona horaria local) de forma predeterminada a UTC en su lugar; SimpleDateFormat es un poco demasiado inteligente para su propio bien.

    Sin embargo, usted puede convencer a cualquiera SimpleDateFormat ejemplo para usar el derecho de la zona de tiempo, si usted lo pone explícitamente en la entrada: sólo anexar una cadena fija a la recibió (y validado adecuadamente) «06:12» para analizar «06:12 GMT» como «HH:MM z».

    No hay necesidad de configuración explícita de GregorianCalendar campos o de la recuperación y uso de la zona horaria y horario de verano de compensaciones.

    El verdadero problema consiste en separar los insumos que de forma predeterminada a la zona horaria local, las aportaciones que de forma predeterminada a UTC y las entradas que realmente requieren de una explícita zona horaria de indicación.

  8. 4

    Algo que me ha funcionado en el pasado fue determinar el desplazamiento (en milisegundos) entre la zona horaria del usuario y GMT. Una vez que usted tiene el desplazamiento, simplemente puede añadir/restar (dependiendo de la manera en la que la conversión se va) para obtener el tiempo apropiado en cualquier zona horaria. Yo suelen lograr esto mediante el establecimiento de los milisegundos de campo de un objeto Calendar, pero estoy seguro que se puede aplicar fácilmente a un objeto de fecha. Este es el código que uso para obtener el desplazamiento

    int offset = TimeZone.getTimeZone(timezoneId).getRawOffset();

    timezoneId es el identificador de la zona horaria del usuario (tal como EST).

    • El uso de la raw de desplazamiento que están haciendo caso omiso de horario de verano.
    • Exactamente, este método va a dar resultados incorrectos durante la mitad del año. La peor forma de error.
  9. 1

    java.tiempo

    El moderno enfoque utiliza la java.tiempo clases que suplantado a la problemática legado de fecha y hora de las clases liado con las primeras versiones de Java.

    La java.sql.Timestamp de clase es uno de esos legado de clases. Ya No es necesario. En lugar de utilizar Instant u otras java.el tiempo de clases directamente con la base de datos mediante JDBC 4.2 y versiones posteriores.

    La Instant clase representa un momento en la línea de tiempo en UTC con una resolución de nanosegundos (hasta nueve (9) dígitos de una fracción decimal).

    Instant instant = myResultSet.getObject(  , Instant.class ) ; 

    Si usted debe interactuar con un Timestamp, convertir de inmediato en java.tiempo a través de los nuevos métodos de conversión añadido a la edad, las clases.

    Instant instant = myTimestamp.toInstant() ;

    Para ajustar en otra zona horaria, especificar la zona horaria como un ZoneId objeto. Especificar un en el tiempo apropiado, el nombre de la zona en el formato de continent/region, tales como America/Montreal, Africa/Casablanca, o Pacific/Auckland. No utilice nunca el 3-4 de la carta de pseudo-zonas tales como EST o IST como son no verdadero zonas de tiempo, no estandarizado, y ni siquiera único(!).

    ZoneId z = ZoneId.of( "America/Montreal" ) ;

    Se aplican a la Instant para producir un ZonedDateTime objeto.

    ZonedDateTime zdt = instant.atZone( z ) ;

    Para generar una cadena para mostrar al usuario la búsqueda de Desbordamiento de Pila para DateTimeFormatter encontrar muchas discusiones y ejemplos.

    Tu Pregunta es realmente acerca de ir en la otra dirección, a partir de los datos de usuario de entrada-a la fecha-hora de objetos. Generalmente las mejores romper la entrada de datos en dos partes, una fecha y una hora del día.

    LocalDate ld = LocalDate.parse( dateInput , DateTimeFormatter.ofPattern( "M/d/uuuu" , Locale.US ) ) ;
    LocalTime lt = LocalTime.parse( timeInput , DateTimeFormatter.ofPattern( "H:m a" , Locale.US ) ) ;

    Tu Pregunta no es clara. ¿Quieres interpretar la fecha y la hora introducida por el usuario en la UTC? O en otra zona horaria?

    Si usted quiere UTC, crear un OffsetDateTime con un desplazamiento utilizando la constante de UTC, ZoneOffset.UTC.

    OffsetDateTime odt = OffsetDateTime.of( ld , lt , ZoneOffset.UTC ) ;

    Si significaba otra zona horaria, se combinan junto con una zona de tiempo de un objeto, un ZoneId. Pero que la zona horaria? Usted puede detectar un tiempo predeterminado de la zona. O, si la crítica, usted debe confirmar con el usuario esté seguro de su intención.

    ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;

    Para obtener un objeto más sencillo que siempre está en UTC, por definición, el extracto de una Instant.

    Instant instant = odt.toInstant() ;

    …o…

    Instant instant = zdt.toInstant() ; 

    Enviar a la base de datos.

    myPreparedStatement.setObject(  , instant ) ;

    Acerca de java.tiempo

    La java.tiempo marco está construido en Java 8 y versiones posteriores. Estas clases suplantar la problemática de edad legado fecha y hora de las clases, tales como java.util.Fecha, Calendario, & SimpleDateFormat.

    La Joda-El Tiempo proyecto, ahora en el modo de mantenimiento, asesora de la migración a la java.tiempo clases.

    Para obtener más información, consulte la Oracle Tutorial. Y la búsqueda de Desbordamiento de Pila, hay muchos ejemplos y explicaciones. La especificación es JSR 310.

    Dónde obtener el java.clases de tiempo?

    • Java SE 8, Java SE 9, y más tarde
      • Incorporado.
      • Parte de la norma API de Java con un paquete de implementación.
      • Java 9 añade algunas características menores y correcciones.
    • Java SE 6 y Java SE 7
      • Mucho de java.el tiempo es la funcionalidad de back-portado a Java 6 & 7 en ThreeTen-Backport.
    • Android
      • Versiones posteriores de Android paquete de implementaciones de java.clases de tiempo.
      • Para versiones anteriores de Android, la ThreeTenABP proyecto se adapta ThreeTen-Backport (mencionado anteriormente). Ver Cómo utilizar ThreeTenABP….

    La ThreeTen-Extra proyecto se extiende java.tiempo con clases adicionales. Este proyecto es un terreno de prueba para posibles futuras incorporaciones a java.tiempo. Usted puede encontrar algunos de clases útiles aquí como Intervalo, YearWeek, YearQuarter, y más.

Dejar respuesta

Please enter your comment!
Please enter your name here