operaciones - Obtención del componente de tiempo de una fecha o calendario de Java
numero a fecha java (10)
¿Existe una manera simple o elegante de capturar solo la hora del día (horas / minutos / segundos / milisegundos) parte de una Fecha Java (o Calendario, realmente no me importa)? Estoy buscando una buena forma de considerar por separado la fecha (año / mes / día) y las partes de la hora del día, pero por lo que puedo decir, no puedo acceder a cada campo por separado.
Sé que podría escribir mi propio método para capturar individualmente los campos que me interesan, pero lo estaría haciendo como un método de utilidad estática, que es feo. Además, sé que los objetos Fecha y Calendario tienen una precisión de milisegundos, pero no veo una forma de acceder al componente de milisegundos en ninguno de los casos.
Edición: no estaba claro al respecto: usar uno de Date :: getTime () o Calendar :: getTimeInMillis no es muy útil para mí, ya que devuelven la cantidad de milisegundos desde la época (representada por esa fecha o calendario) , que en realidad no separa la hora del día del resto de la información.
La respuesta de @ Jherico es lo más cercano, creo, pero definitivamente es algo que todavía tengo que rodar en un método que escribo yo mismo. No es exactamente a lo que me dirijo, ya que aún incluye horas, minutos y segundos en el valor devuelto en milisegundos, aunque probablemente pueda hacerlo funcionar para mis propósitos.
Todavía pienso en cada componente como separado , aunque, por supuesto, no lo son. Puede escribir una hora como el número de milisegundos desde una fecha de referencia arbitraria, o puede escribir exactamente la misma hora que el year/month/day hours:minutes:seconds.milliseconds
.
Esto no es para fines de visualización. Sé cómo usar un DateFormat
para hacer cadenas de fecha bonitas.
Edición 2: mi pregunta original surgió de un pequeño conjunto de funciones de utilidad que me encontré escribiendo, por ejemplo:
- Comprobando si dos
Date
representan una fecha y hora en el mismo día; - Verificación de si una fecha está dentro de un rango especificado por otras dos fechas, pero a veces se comprueba de forma inclusiva, y en ocasiones no, según el componente de tiempo.
¿Tiene Joda Time este tipo de funcionalidad?
Edición 3: la pregunta de @Jon con respecto a mi segundo requisito, solo para aclarar: el segundo requisito es el resultado de utilizar mis Fechas para representar a veces días completos, donde el componente de tiempo no importa en absoluto, y en ocasiones representa una fecha y hora ( que es, IMO, la palabra más precisa para algo que contiene year/month/day
y hours:minutes:seconds:...
).
Cuando una Fecha representa un día completo, sus partes de tiempo son cero (por ejemplo, el "componente de tiempo" de la Fecha es medianoche) pero la semántica dicta que la verificación de rango se realiza inclusive en la fecha final. Debido a que solo dejo esta verificación hasta Fecha: antes y Fecha: después, tengo que agregar 1 día a la fecha de finalización, por lo tanto, la caja especial para cuando el componente de la fecha del día es cero.
Espero que eso no haya dejado las cosas menos claras.
tl; dr
LocalTime lt = myUtilDate.toInstant().atZone( ZoneId.of( "America/Montreal" ) ).toLocalTime() ;
Evitar las clases antiguas de fecha y hora.
Está utilizando antiguas clases de fecha y hora heredadas. Son molestos y confusos; Evítales.
En su lugar, utilice las clases java.time. Estos suplantan a las clases antiguas así como a la biblioteca Joda-Time.
Convertir
Convierte tu java.util.Date
a un Instant
.
La clase Instant
representa un momento en la línea de tiempo en UTC con una resolución de nanoseconds .
Instant instant = myUtilDate.toInstant();
Zona horaria
Aplicar una zona horaria. La zona horaria es crucial. Para cualquier momento dado, la fecha varía alrededor del mundo por zona. Por ejemplo, unos pocos minutos después de la medianoche en París, Francia es un nuevo día y también es "ayer" en Montreal Quebec.
Aplica un ZoneId
para obtener un objeto ZonedDateTime
.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );
Tipos Local…
La clase LocalDate
representa un valor de solo fecha sin hora del día y sin zona horaria. Del mismo modo, LocalTime
representa una hora del día sin una fecha y sin una zona horaria. Puede pensar en estos como dos componentes que junto con un ZoneId
conforman un ZonedDateTime
. Puede extraer estos de un ZonedDateTime
.
LocalDate ld = zdt.toLocalDate();
LocalTime lt = zdt.toLocalTime();
Instrumentos de cuerda
Si su objetivo es simplemente generar cadenas para su presentación al usuario, no necesita los tipos Local…
En su lugar, use DateTimeFormatter
para generar cadenas que representan solo la parte de la fecha o la parte de la hora. Esa clase es lo suficientemente inteligente como para localize automáticamente mientras genera la cadena.
Especifique una Locale
para determinar (a) el lenguaje humano utilizado para traducir el nombre del día, el nombre del mes y similares, y (b) las normas culturales para decidir cuestiones como la abreviatura, el uso de mayúsculas, la puntuación, y otras.
Locale l = Locale.CANADA_FRENCH ; // Or Locale.US, Locale.ITALY, etc.
DateTimeFormatter fDate = DateTimeFormatter.ofLocalizedDate( FormatStyle.MEDIUM ).withLocale( locale );
String outputDate = zdt.format( fDate );
DateTimeFormatter fTime = DateTimeFormatter.ofLocalizedTime( FormatStyle.MEDIUM ).withLocale( locale );
String outputTime = zdt.format( fTime );
Acerca de java.time
El marco java.time está integrado en Java 8 y java.time posteriores. Estas clases sustituyen a las antiguas clases de fecha y hora problemáticas, como java.util.Date
, .Calendar
, & java.text.SimpleDateFormat
.
El proyecto Joda-Time , ahora en modo de mantenimiento , aconseja la migración a java.time.
Para obtener más información, consulte el tutorial de Oracle . Y busca para muchos ejemplos y explicaciones.
Gran parte de la funcionalidad de java.time está respaldada a Java 6 y 7 en ThreeTen-Backport y se adapta aún más a Android en ThreeTenABP (ver Cómo usar ... ).
El proyecto ThreeTen-Extra extiende java.time con clases adicionales. Este proyecto es un terreno de prueba para posibles adiciones futuras a java.time.
¿Por qué quieres separarlos? Si quiere hacer alguna aritmética con la parte del tiempo, rápidamente se metirá en problemas. Si se retira a las 11:59 pm y agrega un minuto, ahora que su hora y el día están separados, se equivocó: tendrá una hora no válida y una fecha incorrecta.
Si solo desea mostrarlos, la aplicación de varios formatos de fecha simples debería proporcionarle exactamente lo que desea.
Si quieres manipular la fecha, te sugiero que obtengas los valores largos y bases todo en eso. En cualquier momento, puede tomar ese tiempo y aplicar un formato para obtener los minutos / horas / segundos que se muestran con bastante facilidad.
Pero solo me preocupa un poco el concepto de manipular el día y la hora por separado, parece como abrir una lata de gusanos. (Sin mencionar los problemas de zona horaria!).
Estoy bastante seguro de que es por eso que Java no tiene una manera fácil de hacer esto.
A continuación, encontrará una solución que emplea Joda Time y admite zonas horarias. Por lo tanto, obtendrá la fecha y la hora (en currentDate
y currentTime
) en la zona horaria actualmente configurada en la JVM.
Tenga en cuenta que Joda Time no admite segundos de salto . Por lo tanto, puede estar a unos 26 o 27 segundos del valor real. Esto probablemente solo se resolverá en los próximos 50 años, cuando el error acumulado se acerque a 1 minuto y la gente comenzará a preocuparse por ello.
Véase también: en.wikipedia.org/wiki/Leap_second
/**
* This class splits the current date/time (now!) and an informed date/time into their components:
* <lu>
* <li>schedulable: if the informed date/time is in the present (now!) or in future.</li>
* <li>informedDate: the date (only) part of the informed date/time</li>
* <li>informedTime: the time (only) part of the informed date/time</li>
* <li>currentDate: the date (only) part of the current date/time (now!)</li>
* <li>currentTime: the time (only) part of the current date/time (now!)</li>
* </lu>
*/
public class ScheduleDateTime {
public final boolean schedulable;
public final long millis;
public final java.util.Date informedDate;
public final java.util.Date informedTime;
public final java.util.Date currentDate;
public final java.util.Date currentTime;
public ScheduleDateTime(long millis) {
final long now = System.currentTimeMillis();
this.schedulable = (millis > -1L) && (millis >= now);
final TimeZoneUtils tz = new TimeZoneUtils();
final java.util.Date dmillis = new java.util.Date( (millis > -1L) ? millis : now );
final java.time.ZonedDateTime zdtmillis = java.time.ZonedDateTime.ofInstant(dmillis.toInstant(), java.time.ZoneId.systemDefault());
final java.util.Date zdmillis = java.util.Date.from(tz.tzdate(zdtmillis));
final java.util.Date ztmillis = new java.util.Date(tz.tztime(zdtmillis));
final java.util.Date dnow = new java.util.Date(now);
final java.time.ZonedDateTime zdtnow = java.time.ZonedDateTime.ofInstant(dnow.toInstant(), java.time.ZoneId.systemDefault());
final java.util.Date zdnow = java.util.Date.from(tz.tzdate(zdtnow));
final java.util.Date ztnow = new java.util.Date(tz.tztime(zdtnow));
this.millis = millis;
this.informedDate = zdmillis;
this.informedTime = ztmillis;
this.currentDate = zdnow;
this.currentTime = ztnow;
}
}
public class TimeZoneUtils {
public java.time.Instant tzdate() {
final java.time.ZonedDateTime zdtime = java.time.ZonedDateTime.now();
return tzdate(zdtime);
}
public java.time.Instant tzdate(java.time.ZonedDateTime zdtime) {
final java.time.ZonedDateTime zddate = zdtime.truncatedTo(java.time.temporal.ChronoUnit.DAYS);
final java.time.Instant instant = zddate.toInstant();
return instant;
}
public long tztime() {
final java.time.ZonedDateTime zdtime = java.time.ZonedDateTime.now();
return tztime(zdtime);
}
public long tztime(java.time.ZonedDateTime zdtime) {
final java.time.ZonedDateTime zddate = zdtime.truncatedTo(java.time.temporal.ChronoUnit.DAYS);
final long millis = zddate.until(zdtime, java.time.temporal.ChronoUnit.MILLIS);
return millis;
}
}
Bueno, sé que esta es una respuesta predecible, pero ... usa Joda Time . Eso tiene representaciones separadas para "una fecha", "un instante", "una hora del día", etc. Es una API más rica y generalmente más sensata que las clases incorporadas, la OMI.
Si esta es la única manipulación de fecha / hora en la que está interesado, entonces puede ser una exageración ... pero si está usando la API de fecha / hora incorporada para algo importante, le recomiendo encarecidamente que se mude Lejos de ello a Joda tan pronto como sea posible.
Además, debes considerar en qué zona horaria estás interesado. Un Calendar
tiene una zona horaria asociada, pero una Date
no (solo representa un instante en el tiempo, medido en milisegundos desde la época de Unix).
Extraer la parte del tiempo del día debe ser una cuestión de obtener la cantidad restante de milisegundos cuando se divide por la cantidad de milisegundos por día.
long MILLIS_PER_DAY = 24 * 60 * 60 * 1000;
Date now = Calendar.getInstance().getTime();
long timePortion = now.getTime() % MILLIS_PER_DAY;
Alternativamente, considere usar joda-time, una biblioteca de tiempo con todas las funciones.
Para obtener la hora exacta de Joda-Time, use la clase org.joda.time.LocalTime
como se describe en esta pregunta, Joda-Time, Time without date .
En cuanto a comparar fechas solo mientras se ignora efectivamente la hora, en Joda-Time llame al método withTimeAtStartOfDay()
en cada instancia de DateTime
para establecer un valor de tiempo idéntico. Aquí hay un código de ejemplo que usa Joda-Time 2.3, similar al que publiqué en otra respuesta hoy.
// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
// Joda-Time - The popular alternative to Sun/Oracle''s notoriously bad date, time, and calendar classes bundled with Java 7 and earlier.
// http://www.joda.org/joda-time/
// Joda-Time will become outmoded by the JSR 310 Date and Time API introduced in Java 8.
// JSR 310 was inspired by Joda-Time but is not directly based on it.
// http://jcp.org/en/jsr/detail?id=310
// By default, Joda-Time produces strings in the standard ISO 8601 format.
// https://en.wikipedia.org/wiki/ISO_8601
// Capture one moment in time.
org.joda.time.DateTime now = new org.joda.time.DateTime();
System.out.println("Now: " + now);
// Calculate approximately same time yesterday.
org.joda.time.DateTime yesterday = now.minusDays(1);
System.out.println("Yesterday: " + yesterday);
// Compare dates. A DateTime includes time (hence the name).
// So effectively eliminate the time by setting to start of day.
Boolean isTodaySameDateAsYesterday = now.withTimeAtStartOfDay().isEqual(yesterday.withTimeAtStartOfDay());
System.out.println("Is today same date as yesterday: " + isTodaySameDateAsYesterday);
org.joda.time.DateTime halloweenInUnitedStates = new org.joda.time.DateTime(2013, 10, 31, 0, 0);
Boolean isFirstMomentSameDateAsHalloween = now.withTimeAtStartOfDay().isEqual(halloweenInUnitedStates.withTimeAtStartOfDay());
System.out.println("Is now the same date as Halloween in the US: " + isFirstMomentSameDateAsHalloween);
Para responder una parte, el acceso al componente de milisegundos se realiza de la siguiente manera:
long mill = Calendar.getInstance().getTime();
No sé qué desea hacer con los detalles, pero podría usar la clase java.text.SimpleDateFormat si es para salida de texto.
Puede llamar a la función getTimeInMillis () en un objeto Calendario para obtener el tiempo en milisegundos. Puede llamar a get (Calendar.MILLISECOND) en un objeto de calendario para obtener los milisegundos del segundo. Si desea mostrar la hora desde un objeto Fecha o Calendario, use la clase DateFormat. Ejemplo: DateFormat.getTimeInstance (). Format (now). También hay una clase SimpleDateFormat que puedes usar.
Si todo lo que le preocupa es ponerlo en una Cadena para mostrarlo o guardarlo, simplemente cree un SimpleDateFormat que solo muestre la parte del tiempo, como el nuevo SimpleDateFormat ("HH: mm: ss"). La fecha todavía está en el objeto Date, por supuesto, pero no te importa.
Si desea hacer aritmética en él, como tomar dos objetos de fecha y encontrar cuántos segundos de diferencia están al ignorar la parte de la fecha, de modo que "2009-09-01 11:00:00" menos "1941-12-07 09 : 00: 00 "equivale a 2 horas, entonces creo que necesita usar una solución como la de Jherico: obtenga el tiempo largo y llévelo al módulo 1 día.
Usando la API del calendario -
Solución 1-
Calendar c = Calendar.getInstance();
String timeComp = c.get(Calendar.HOUR_OF_DAY)+":"+c.get(Calendar.MINUTE)+":"+c.get(Calendar.SECOND)+":"+c.get(Calendar.MILLISECOND);
System.out.println(timeComp);
salida - 13: 24: 54: 212
Solución 2-
SimpleDateFormat time_format = new SimpleDateFormat("HH:mm:ss.SSS");
String timeComp = time_format.format(Calendar.getInstance().getTime());
salida - 15: 57: 25.518