tomar - tiempo en nanosegundos java
¿Cómo mido el tiempo transcurrido en Java? (15)
Esta pregunta ya tiene una respuesta aquí:
Quiero tener algo como esto:
public class Stream
{
public startTime;
public endTime;
public getDuration()
{
return startTime - endTime;
}
}
También es importante que, por ejemplo, si el tiempo de inicio es a las 23:00 y el tiempo de finalización a la 1:00 para obtener una duración de 2:00.
¿Qué tipos usar para lograr esto en Java?
¿Qué tipos usar para lograr esto en Java?
La respuesta corta es long
. Ahora, más sobre cómo medir ...
System.currentTimeMillis ()
La forma "tradicional" de hacer esto es, de hecho, usar System.currentTimeMillis()
:
long startTime = System.currentTimeMillis();
// ... do something ...
long estimatedTime = System.currentTimeMillis() - startTime;
oacltStopWatch
Tenga en cuenta que Commons Lang tiene una clase StopWatch que se puede usar para medir el tiempo de ejecución en milisegundos. Tiene métodos como split()
, suspend()
, resume()
, etc. que permiten tomar medidas en diferentes puntos de la ejecución y que usted puede encontrar conveniente. Échale un vistazo.
System.nanoTime ()
Es posible que prefiera usar System.nanoTime()
si está buscando mediciones extremadamente precisas del tiempo transcurrido. Desde su javadoc:
long startTime = System.nanoTime();
// ... the code being measured ...
long estimatedTime = System.nanoTime() - startTime;
Jamon
Otra opción sería usar JAMon , una herramienta que recopila estadísticas (tiempo de ejecución, número de aciertos, tiempo de ejecución promedio, mínimo, máximo, etc.) para cualquier código que se interponga entre los métodos de inicio () y parada (). A continuación, un ejemplo muy simple:
import com.jamonapi.*;
...
Monitor mon=MonitorFactory.start("myFirstMonitor");
...Code Being Timed...
mon.stop();
Echa un vistazo a este artículo en www.javaperformancetunning.com para una buena introducción.
Utilizando AOP
Finalmente, si no desea saturar su código con estas medidas (o si no puede cambiar el código existente), AOP sería un arma perfecta. No voy a discutir esto muy a fondo, pero al menos quería mencionarlo.
A continuación, un aspecto muy simple con AspectJ y JAMon (aquí, el nombre corto del punto de corte se usará para el monitor JAMon, de ahí la llamada a thisJoinPoint.toShortString()
):
public aspect MonitorAspect {
pointcut monitor() : execution(* *.ClassToMonitor.methodToMonitor(..));
Object arround() : monitor() {
Monitor monitor = MonitorFactory.start(thisJoinPoint.toShortString());
Object returnedObject = proceed();
monitor.stop();
return returnedObject;
}
}
La definición del punto de corte podría adaptarse fácilmente para monitorear cualquier método basado en el nombre de la clase, el nombre del paquete, el nombre del método o cualquier combinación de estos. La medición es realmente un caso de uso perfecto para AOP.
¿Qué tipos usar para lograr esto en Java?
Respuesta : largo
public class Stream {
public long startTime;
public long endTime;
public long getDuration() {
return endTime - startTime;
}
// I would add
public void start() {
startTime = System.currentTimeMillis();
}
public void stop() {
endTime = System.currentTimeMillis();
}
}
Uso:
Stream s = ....
s.start();
// do something for a while
s.stop();
s.getDuration(); // gives the elapsed time in milliseconds.
Esa es mi respuesta directa para tu primera pregunta.
Para la última "nota" te sugiero que uses Joda Time. Contiene una clase de interval adecuada para lo que necesita.
tl; dr
por ejemplo, si el tiempo de inicio es 23:00 y el tiempo final 1:00 para obtener una duración de 2:00.
Imposible. Si solo tiene la hora del día, el reloj se detiene a la medianoche. Sin el contexto de las fechas, ¿cómo sabemos si te refieres a 1 AM el día siguiente, la semana que viene o la próxima década?
Así que pasar de las 11 PM a la 1 AM significa retroceder en el tiempo 22 horas, pasando las manecillas del reloj en sentido contrario a las agujas del reloj. Vea el resultado a continuación, veintidós horas negativas .
Duration.between( // Represent a span of time a total number of seconds plus a fractional second in nanoseconds.
LocalTime.of( 23 , 0 ) , // A time-of-day without a date and without a time zone.
LocalTime.of( 1 , 0 ) // A time-of-day clock stops at midnight. So getting to 1 AM from 11 PM means going backwards 22 hours.
) // Return a `Duration` object.
.toString() // Generate a `String` representing this span of time using standard ISO 8601 format: PnYnMnDTnHnMnS
PT-22H
Cruzar la medianoche requiere un contexto más amplio de fecha además de la hora del día (ver más abajo).
¿Cómo mido el tiempo transcurrido en Java?
- Captura el momento actual en UTC, con
Instant.now()
. - Captura otro momento más tarde.
- Pasar los dos a
Duration.between
. - (a) Del objeto
Duration
resultante, extraiga una cantidad de días, horas, minutos, segundos y segundo fraccional de 24 horas en nanosegundos llamando a los métodos de variosto…Part
.
(b) O llame atoString
para generar unaString
en formato ISO 8601 estándar dePnYnMnDTnHnMnS
.
Código de ejemplo, utilizando un par de objetos Instant
.
Duration.between( // Represent a span of time a total number of seconds plus a fractional second in nanoseconds.
then , // Some other `Instant` object, captured earlier with `Instant.now()`.
Instant.now() // Capture the current moment in UTC with a resolution as fine as nanoseconds, depending on the limits of your host computer hardware clock and operating system. Generally you will get current moment in microseconds (six decimal digits of fractional second) in Java 9, 10, and 11, but only milliseconds in Java 8.
) // Return a `Duration` object.
.toString() // Generate a `String` representing this span of time using standard ISO 8601 format: PnYnMnDTnHnMnS
PT3M27.602197S
Nueva tecnología en Java 8+
Tenemos una nueva tecnología para esto ahora integrada en Java 8 y posterior, el marco java.time .
java.time
El marco java.time está definido por JSR 310 , inspirado en el exitoso proyecto Joda-Time , ampliado por el proyecto ThreeTen-Extra y descrito en el Tutorial de Oracle .
Las antiguas clases de fecha y hora, como java.util.Date/.Calendar con las primeras versiones de Java, han demostrado estar mal diseñadas, ser confusas y problemáticas. Son suplantados por las clases java.time.
Resolución
Otras respuestas discuten la resolución.
Las clases de java.time tienen una resolución de nanosecond , hasta nueve dígitos de una fracción decimal de segundo. Por ejemplo, 2016-03-12T04:29:39.123456789Z
.
Tanto la antigua clase java.util.Date/.Calendar como la clase Joda-Time tienen una resolución de milisegundos (3 dígitos de fracción). Por ejemplo, 2016-03-12T04:29:39.123Z
.
En Java 8, el momento actual se recupera con una resolución de solo un milisegundo debido a un problema heredado. En Java 9 y versiones posteriores, la hora actual se puede determinar hasta una resolución de nanosegundos siempre que el reloj del hardware de su computadora funcione tan bien.
Hora del dia
Si realmente desea trabajar solo con la hora del día que falta en cualquier fecha o zona horaria, use la clase LocalTime
.
LocalTime sooner = LocalTime.of ( 17, 00 );
LocalTime later = LocalTime.of ( 19, 00 );
Una Duration
representa un lapso de tiempo en términos de una cuenta de segundos más nanosegundos.
Duration duration = Duration.between ( sooner, later );
Volcar a la consola.
System.out.println ( "sooner: " + sooner + " | later: " + later + " | duration: " + duration );
antes: 17:00 | después: 19:00 | duración: PT2H
ISO 8601
Observe que la salida predeterminada de Duration::toString
está en formato estándar ISO 8601 . En este formato, la P
marca el comienzo (como en ''Período''), y la T
separa cualquier porción de años-meses-días de la porción de horas-minutos-segundos.
Cruzando la medianoche
Desafortunadamente, trabajar con la hora del día solo se vuelve complicado cuando se cierra todo el día cruzando la medianoche. La clase LocalTime
maneja esto asumiendo que desea retroceder a un punto anterior del día.
El uso del mismo código que el anterior pero de 23:00
a 01:00
da como resultado veintidós horas negativas ( PT-22H
).
LocalTime sooner = LocalTime.of ( 23, 0 );
LocalTime later = LocalTime.of ( 1, 0 );
antes: 23:00 | después: 01:00 | duración: PT-22H
Fecha y hora
Si pretende cruzar la medianoche, probablemente tenga sentido que trabaje con valores de fecha y hora en lugar de valores de solo hora del día.
Zona horaria
La zona horaria es crucial para las fechas. Por lo tanto, especificamos tres elementos: (1) la fecha deseada, (2) la hora del día deseada y (3) la zona horaria como un contexto para interpretar esa fecha y hora. Aquí elegimos arbitrariamente la zona horaria de la zona de Montréal .
Si define la fecha solo por un offset-from-UTC , use un ZoneOffset
con un OffsetDateTime
. Si tiene una zona horaria completa (reglas de compensación más para el manejo de anomalías, como el horario de verano), use un ZoneId
con un ZonedDateTime
.
LocalDate localDate = LocalDate.of ( 2016, 1, 23 );
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime sooner = ZonedDateTime.of ( localDate, LocalTime.of ( 23, 0 ), zoneId );
Especificamos la hora posterior como el día siguiente a la 1:00 AM.
ZonedDateTime later = ZonedDateTime.of ( localDate.plusDays ( 1 ), LocalTime.of ( 1, 0 ), zoneId );
Calculamos la Duration
de la misma manera que se vio anteriormente. Ahora tenemos las dos horas esperadas por esta pregunta.
Duration duration = Duration.between ( sooner, later );
Volcar a la consola.
System.out.println ( "sooner: " + sooner + " | later: " + later + " | duration: " + duration );
antes: 2016-01-23T23: 00-05: 00 [América / Montreal] | más tarde: 2016-01-24T01: 00-05: 00 [América / Montreal] | duración: PT2H
Horario de verano
Si las fechas y las fechas disponibles tuvieran que ver con el horario de verano u otras anomalías similares, las clases de java.time se ajustarán según sea necesario. Lea la clase doc para más detalles.
Acerca de java.time
El marco java.time está integrado en Java 8 y java.time posteriores. Estas clases sustituyen a las antiguas y problemáticas clases de fecha y hora como java.util.Date
, Calendar
y SimpleDateFormat
.
El proyecto Joda-Time , ahora en modo de mantenimiento , aconseja la migración a las clases java.time .
Para obtener más información, consulte el Tutorial de Oracle . Y busca para muchos ejemplos y explicaciones. La especificación es JSR 310 .
Puede intercambiar objetos java.time directamente con su base de datos. Utilice un controlador JDBC compatible con JDBC 4.2 o posterior. No se necesitan cadenas, no se necesitan clases java.sql.*
.
¿Dónde obtener las clases java.time?
- Java SE 8 , Java SE 9 , Java SE 10 y posteriores
- Incorporado.
- Parte de la API de Java estándar con una implementación en paquete.
- Java 9 agrega algunas características menores y correcciones.
- Java SE 6 y Java SE 7
- Gran parte de la funcionalidad de java.time está respaldada a Java 6 y 7 en ThreeTen-Backport .
- Android
- Versiones posteriores de las implementaciones de paquetes de Android de las clases java.time.
- Para Android anterior (<26), el proyecto ThreeTenABP adapta ThreeTen-Backport (mencionado anteriormente). Vea Cómo usar ThreeTenABP… .
El proyecto ThreeTen-Extra extiende java.time con clases adicionales. Este proyecto es un terreno de prueba para posibles adiciones futuras a java.time. Puede encontrar algunas clases útiles aquí como Interval
, YearWeek
, YearQuarter
, y more .
Cabe resaltar que
- System.currentTimeMillis () tiene una precisión de solo milisegundos en el mejor de los casos. Vale la pena su puede ser de 16 ms en algunos sistemas de Windows. Tiene un costo menor que las alternativas <200 ns.
- System.nanoTime () solo tiene precisión de micro segundos en la mayoría de los sistemas y puede saltar a los sistemas de Windows en 100 microsegundos (es decir, a veces no es tan preciso como parece)
- El calendario es una forma muy costosa de calcular el tiempo. (puedo pensar en aparte de XMLGregorianCalendar) A veces es la solución más apropiada, pero tenga en cuenta que solo debe tomar intervalos de tiempo prolongados.
Construí una función de formato basada en cosas que robé SO. Necesitaba una forma de "perfilar" las cosas en los mensajes de registro, así que necesitaba un mensaje de duración de longitud fija.
public static String GetElapsed(long aInitialTime, long aEndTime, boolean aIncludeMillis)
{
StringBuffer elapsed = new StringBuffer();
Map<String, Long> units = new HashMap<String, Long>();
long milliseconds = aEndTime - aInitialTime;
long seconds = milliseconds / 1000;
long minutes = milliseconds / (60 * 1000);
long hours = milliseconds / (60 * 60 * 1000);
long days = milliseconds / (24 * 60 * 60 * 1000);
units.put("milliseconds", milliseconds);
units.put("seconds", seconds);
units.put("minutes", minutes);
units.put("hours", hours);
units.put("days", days);
if (days > 0)
{
long leftoverHours = hours % 24;
units.put("hours", leftoverHours);
}
if (hours > 0)
{
long leftoeverMinutes = minutes % 60;
units.put("minutes", leftoeverMinutes);
}
if (minutes > 0)
{
long leftoverSeconds = seconds % 60;
units.put("seconds", leftoverSeconds);
}
if (seconds > 0)
{
long leftoverMilliseconds = milliseconds % 1000;
units.put("milliseconds", leftoverMilliseconds);
}
elapsed.append(PrependZeroIfNeeded(units.get("days")) + " days ")
.append(PrependZeroIfNeeded(units.get("hours")) + " hours ")
.append(PrependZeroIfNeeded(units.get("minutes")) + " minutes ")
.append(PrependZeroIfNeeded(units.get("seconds")) + " seconds ")
.append(PrependZeroIfNeeded(units.get("milliseconds")) + " ms");
return elapsed.toString();
}
private static String PrependZeroIfNeeded(long aValue)
{
return aValue < 10 ? "0" + aValue : Long.toString(aValue);
}
Y una clase de prueba:
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import junit.framework.TestCase;
public class TimeUtilsTest extends TestCase
{
public void testGetElapsed()
{
long start = System.currentTimeMillis();
GregorianCalendar calendar = (GregorianCalendar) Calendar.getInstance();
calendar.setTime(new Date(start));
calendar.add(Calendar.MILLISECOND, 610);
calendar.add(Calendar.SECOND, 35);
calendar.add(Calendar.MINUTE, 5);
calendar.add(Calendar.DAY_OF_YEAR, 5);
long end = calendar.getTimeInMillis();
assertEquals("05 days 00 hours 05 minutes 35 seconds 610 ms", TimeUtils.GetElapsed(start, end, true));
}
}
Desafortunadamente, ninguna de las diez respuestas publicadas hasta el momento es correcta.
Si está midiendo el tiempo transcurrido, y desea que sea correcto , debe usar System.nanoTime()
. No puedes usar System.currentTimeMillis()
, a menos que no te importe que tu resultado sea incorrecto.
El propósito de nanoTime
es medir el tiempo transcurrido , y el propósito de currentTimeMillis
es medir el tiempo de reloj de pared . No puedes usar el uno para el otro propósito. La razón es que ningún reloj de computadora es perfecto; siempre deriva y ocasionalmente necesita ser corregido. Esta corrección puede suceder manualmente, o en el caso de la mayoría de las máquinas, hay un proceso que se ejecuta y continuamente emite pequeñas correcciones al reloj del sistema ("reloj de pared"). Estos tienden a suceder a menudo. Otra corrección de este tipo ocurre cuando hay un segundo de salto.
Dado que el propósito de nanoTime
es medir el tiempo transcurrido, no se ve afectado por ninguna de estas pequeñas correcciones. Es lo que quieres usar. Cualquier tiempo actualmente en curso con currentTimeMillis
estará apagado, posiblemente incluso negativo.
Puede decir, "esto no suena como si realmente importara tanto", a lo que le digo, tal vez no, pero en general, ¿no es el código correcto simplemente mejor que el código incorrecto? Además, nanoTime
es más corto de escribir de todos modos.
Las exenciones de responsabilidad publicadas anteriormente sobre nanoTime
generalmente tienen solo una precisión de microsegundos son válidas. También puede tardar más de un microsegundo entero en invocar, dependiendo de las circunstancias (al igual que la otra), por lo que no espere intervalos muy pequeños correctamente.
Encontré que este código es útil para sincronizar cosas:
public class Et {
public Et() {
reset();
}
public void reset() {
t0=System.nanoTime();
}
public long t0() {
return t0;
}
public long dt() {
return System.nanoTime()-t0();
}
public double etms() {
return etms(dt());
}
@Override public String toString() {
return etms()+" ms.";
}
public static double etms(long dt) {
return dt/1000000.; // 1_000_000. breaks cobertura
}
private Long t0;
}
Java proporciona el método estático System.currentTimeMillis()
. Y eso está devolviendo un valor largo, por lo que es una buena referencia. Muchas otras clases aceptan un parámetro ''timeInMillis'' que también es largo.
Y a muchas personas les resulta más fácil usar la biblioteca de Joda Time para hacer cálculos en fechas y horas.
Si el propósito es simplemente imprimir información de tiempo aproximado en los registros de su programa, entonces la solución fácil para los proyectos Java es no escribir sus propias clases de cronómetro o temporizador, sino simplemente usar la clase org.apache.commons.lang.time.StopWatch
que Es parte de Apache Commons Lang.
final StopWatch stopwatch = new StopWatch();
stopwatch.start();
LOGGER.debug("Starting long calculations: {}", stopwatch);
...
LOGGER.debug("Time after key part of calcuation: {}", stopwatch);
...
LOGGER.debug("Finished calculating {}", stopwatch);
Si está escribiendo una aplicación que debe lidiar con la duración del tiempo, por favor, eche un vistazo a Joda-Time, que tiene clase específicamente para el manejo de duraciones, interval y períodos. Su método getDuration()
parece que podría devolver un intervalo Joda-Time:
DateTime start = new DateTime(2004, 12, 25, 0, 0, 0, 0);
DateTime end = new DateTime(2005, 1, 1, 0, 0, 0, 0);
public Interval getInterval() {
Interval interval = new Interval(start, end);
}
Si obtienes tus marcas de tiempo de System.currentTimeMillis()
, entonces tus variables de tiempo deberían ser largas.
Si prefieres usar la API de calendario de Java, puedes probar esto,
Date startingTime = Calendar.getInstance().getTime();
//later on
Date now = Calendar.getInstance().getTime();
long timeElapsed = now.getTime() - startingTime.getTime();
Tu nueva clase:
public class TimeWatch {
long starts;
public static TimeWatch start() {
return new TimeWatch();
}
private TimeWatch() {
reset();
}
public TimeWatch reset() {
starts = System.currentTimeMillis();
return this;
}
public long time() {
long ends = System.currentTimeMillis();
return ends - starts;
}
public long time(TimeUnit unit) {
return unit.convert(time(), TimeUnit.MILLISECONDS);
}
}
Uso:
TimeWatch watch = TimeWatch.start();
// do something
long passedTimeInMs = watch.time();
long passedTimeInSeconds = watch.time(TimeUnit.SECONDS);
Después, el tiempo transcurrido se puede convertir al formato que desee, por ejemplo, con un calendario.
Greetz, GHad
Utilizar esta:
SimpleDateFormat format = new SimpleDateFormat("HH:mm");
Date d1 = format.parse(strStartTime);
Date d2 = format.parse(strEndTime);
long diff = d2.getTime() - d1.getTime();
long diffSeconds,diffMinutes,diffHours;
if (diff > 0) {
diffSeconds = diff / 1000 % 60;
diffMinutes = diff / (60 * 1000) % 60;
diffHours = diff / (60 * 60 * 1000);
}
else{
long diffpos = (24*((60 * 60 * 1000))) + diff;
diffSeconds = diffpos / 1000 % 60;
diffMinutes = diffpos / (60 * 1000) % 60;
diffHours = (diffpos / (60 * 60 * 1000));
}
(También es importante que, por ejemplo, si la hora de inicio es las 23:00 y la hora de finalización 1:00 para obtener una duración de 2:00.)
la parte "else" puede hacerlo correctamente
Byte Stream Reader Elapsed Time for 23.7 MB is 96 secs
import java.io.*;
import java.io.IOException;
import java.util.Scanner;
class ElaspedTimetoCopyAFileUsingByteStream
{
private long startTime = 0;
private long stopTime = 0;
private boolean running = false;
public void start()
{
this.startTime = System.currentTimeMillis();
this.running = true;
}
public void stop()
{
this.stopTime = System.currentTimeMillis();
this.running = false;
}
public long getElapsedTime()
{
long elapsed;
if (running) {
elapsed = (System.currentTimeMillis() - startTime);
}
else {
elapsed = (stopTime - startTime);
}
return elapsed;
}
public long getElapsedTimeSecs()
{
long elapsed;
if (running)
{
elapsed = ((System.currentTimeMillis() - startTime) / 1000);
}
else
{
elapsed = ((stopTime - startTime) / 1000);
}
return elapsed;
}
public static void main(String[] args) throws IOException
{
ElaspedTimetoCopyAFileUsingByteStream s = new ElaspedTimetoCopyAFileUsingByteStream();
s.start();
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream("vowels.txt"); // 23.7 MB File
out = new FileOutputStream("output.txt");
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
}finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
s.stop();
System.out.println("elapsed time in seconds: " + s.getElapsedTimeSecs());
}
}
[Elapsed Time for Byte Stream Reader][1]
**Character Stream Reader Elapsed Time for 23.7 MB is 3 secs**
import java.io.*;
import java.io.IOException;
import java.util.Scanner;
class ElaspedTimetoCopyAFileUsingCharacterStream
{
private long startTime = 0;
private long stopTime = 0;
private boolean running = false;
public void start()
{
this.startTime = System.currentTimeMillis();
this.running = true;
}
public void stop()
{
this.stopTime = System.currentTimeMillis();
this.running = false;
}
public long getElapsedTime()
{
long elapsed;
if (running) {
elapsed = (System.currentTimeMillis() - startTime);
}
else {
elapsed = (stopTime - startTime);
}
return elapsed;
}
public long getElapsedTimeSecs()
{
long elapsed;
if (running)
{
elapsed = ((System.currentTimeMillis() - startTime) / 1000);
}
else
{
elapsed = ((stopTime - startTime) / 1000);
}
return elapsed;
}
public static void main(String[] args) throws IOException
{
ElaspedTimetoCopyAFileUsingCharacterStream s = new ElaspedTimetoCopyAFileUsingCharacterStream();
s.start();
FileReader in = null; // CharacterStream Reader
FileWriter out = null;
try {
in = new FileReader("vowels.txt"); // 23.7 MB
out = new FileWriter("output.txt");
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
}finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
s.stop();
System.out.println("elapsed time in seconds: " + s.getElapsedTimeSecs());
}
}
[Elapsed Time for Character Stream Reader][2]
[1]: https://i.stack.imgur.com/hYo8y.png
[2]: https://i.stack.imgur.com/xPjCK.png