Proper way to get EPOCH timestamp in kotlin - java

I want to get the EPOCH timestamp in kotlin in "seconds":"nanoseconds" format.
Note: Please look at the accepted answer for the right solution.
Edit:
It's my current solution and I'm sure there would be some better way to achieve this,
import java.time.Instant
import java.time.temporal.ChronoUnit;
import kotlin.time.Duration.Companion.seconds
fun main() {
val epochNanoseconds = ChronoUnit.NANOS.between(Instant.EPOCH, Instant.now())
val epochSeconds = epochNanoseconds/1.seconds.inWholeNanoseconds
val remainingFractionOfNanoSeconds = epochNanoseconds%1.seconds.inWholeNanoseconds
println("$epochSeconds:$remainingFractionOfNanoSeconds")
}
example output:
1670251213:849754000
Another example (from the comments): For 1670251213 seconds 50000 nanoseconds, also known as 1670251213.00005 seconds in decimal, I want 1670251213:50000 (means :).
Is there any way to get seconds and remaining nanoseconds directly from java.time.Instant or any other library available to achieve this conveniently?
Solution from the accepted answer:
import java.time.Instant
fun main() {
val time = Instant.now()
println("${time.epochSecond}:${time.nano}")
}

tl;dr
You are working too hard.
Ask the Instant object for its count of whole seconds since 1970-01-01T00:00Z. Make a string of that, append the COLON character. Then append the count of nanoseconds in the fractional second of the Instant.
instant.getEpochSecond()
+ ":"
+ instant.getNano()
1670220134:130848
Details
Neither the legacy date-time classes (Calendar, Date, etc.) nor the modern java.time classes support International Atomic Time (TAI) that you requested. Time-keeping on conventional computers (and therefore Java) is nowhere near as accurate as an atomic clock.
Perhaps you used that term loosely, and really just want a count of nanoseconds since the epoch reference of first moment of 1970 as seen with an offset from UTC of zero hours-minutes-seconds (1970-01-01T00:00Z) within the limits of conventional computer hardware.
If so, the Instant class will work for you. But beware of limitations in the implementations of Java based on the OpenJDK codebase.
In Java 8, the first with java.time classes, the current moment is captured with a resolution of milliseconds.
In Java 9+, the current moment is captured with a resolution of microseconds (generally, depending on the limits of your computer hardware).
Note that in all versions (8, 9, and later), an Instant is capable of nanosecond resolution. The limitations bulleted above relate to capturing the current moment from the computer hardware clock.
The internal representation of a moment in the Instant class comprises two parts:
A count of whole seconds since 1970-01-01T00:00Z.
A fractional second represented by a count of nanoseconds.
The Instant class provides a pair of accessor methods (getters) to see both of these numbers.
getEpochSecond
getNano
Your Question is not entirely clear, you seem to be asking for those two numbers with a COLON character between them.
Instant instant = Instant.now() ;
String nanos = Long.toString( instant.getNano() ) ;
String output =
instant.getEpochSecond()
+ ":"
+ instant.getNano()
;
instant.toString(): 2022-12-05T06:12:33.294698Z
output: 1670220753:294698
If you want to pad zeros to the right of your fractional second, use String.format.
Instant instant = Instant.now() ;
String nanos = Long.toString( instant.getNano() ) ;
String output =
instant.getEpochSecond()
+ ":"
+ String.format( "%1$" + nanos.length() + "s", nanos ).replace(' ', '0') // Pad with leading zeros if needed.
;
See this code run at Ideone.com.
instant.toString(): 2022-12-05T06:12:33.294698Z
output: 1670220753:294698000
Alternatively, you could instantiate a BigDecimal object.

Related

Converting LocalDateTime to Instant give different values

I am trying to use LocalDateTime to manipulate dates in my application but I have noticed that getting epoch seconds from it returns different values from what I expected
val now1 = Instant.now().epochSecond - 60
val now2 = Instant.now().minusSeconds(60).epochSecond
val now3 = LocalDateTime.now().minusSeconds(60).toEpochSecond(ZoneOffset.UTC)
val now4 = System.currentTimeMillis() / 1000 - 60
Output
Now1 = 1674501451
Now2 = 1674501451
Now3 = 1674512251
Now4 = 1674501451
Notice how Now3 has a different value. What is happening?
tl;dr
Your JVM’s current default time zone is three hours ahead of UTC. Thus your result.( 1_674_512_251L - 1_674_501_451L ) = 3 hours.
👉 You are making inappropriate use of LocalDateTime class.
Moment versus not-a-moment
I am trying to use LocalDateTime to manipulate dates
Don't.
If you are representing a moment, a specific point on the timeline, 👉 do not use LocalDateTime. That class holds a date with a time-of-day but lacks the context of a time zone or offset-from-UTC. To represent a moment use:
Instant — A moment as seen in UTC (an offset from UTC of zero hours-minutes-seconds).
OffsetDateTime - A moment as seen with a particular offset.
ZonedDateTime - A moment as seen through a particular time zone.
I cannot imagine any scenario where calling LocalDateTime.now is the right thing to do.
Example code:
Instant instant = Instant.now() ;
ZoneOffset offset = ZoneId.of( "Africa/Dar_es_Salaam" ).getRules().getOffset( instant ) ;
OffsetDateTime odt = OffsetDateTime.now( offset ) ;
ZoneId zone = ZoneId.of( "Africa/Dar_es_Salaam" ) ;
ZonedDateTime zonedDateTime = ZonedDateTime.now( zone )
Dump to console.
System.out.println( instant + " | " + instant.getEpochSecond() ) ;
System.out.println( odt + " | " + odt.toEpochSecond() ) ;
System.out.println( zonedDateTime + " | " + zonedDateTime.toEpochSecond() ) ;
See this code run at Ideone.com. Note that all three are within the same second, give or take a second as the clock may rollover to the next second by the second or third call to now.
2023-01-24T14:27:06.416597Z | 1674570426
2023-01-24T17:27:06.478680+03:00 | 1674570426
2023-01-24T17:27:06.487289+03:00[Africa/Dar_es_Salaam] | 1674570426
LocalDateTime#toEpochSecond
Calling the toEpochSecond method on LocalDateTime is tricky conceptually. As a concept, LocalDateTime has no epoch reference point. It is just a date with a time. For example, “noon on January 23 of 2023” by itself has no specific meaning, cannot be nailed down to a point on the timeline. So it is meaningless to compare “noon on January 23 of 2023” to a reference point such as the first moment of 1970 as seen in UTC, 1970-01-01T00:00Z.
Practically, the LocalDateTime class is implemented as if it were in UTC. So internally, the class counts a number of whole seconds since 1970-01-01T00:00Z plus a count of nanoseconds for a fractional second. But you should not be thinking of this implementation detail when writing code for business logic. For business logic, calling LocalDateTime#toEpochSecond makes no sense.
Technically speaking
So the technical answer to your Question is that your delta of 3 hours (1_674_501_451L - 1_674_512_251L) came from the fact that your JVM’s current default time zone at that moment used an offset of +03:00, three hours ahead of UTC. So your call to LocalDateTime.now captured a date and time three hours ahead of UTC. But then you asked for toEpochSecond which treats that very same date and time as if it were in UTC.
Logically speaking
Of course that date and time were not meant to represent a moment in UTC. So logically speaking, your code is nonsensical. You should not be comparing a count from epoch for a LocalDateTime (which is a non-moment) to other classes such as Instant (which is a moment).
In other words, you are comparing apples and oranges.
Serializing date-time data
So, if LocalDateTime#toEpochSecond is inappropriate for business logic, why does that class offer such a method?
That method is useful for serializing a LocalDateTime value for storage or data-exchange. Some other systems may present date-with-time values in this manner.
ISO 8601
However, using a count-from-reference is a poor way to communicate date-time values. The values are ambiguous, as their granularity is implicit, and their particular epoch reference point is also implicit. And, such values make validation and debugging difficult for human readers.
I strongly recommend using standard ISO 8601 text rather than a count when storing or exchanging date-time values outside Java. Regarding your example standard textual format would be:
2023-01-23T22:17:31
General advice: Avoid LocalDateTime class unless you are very clear on its appropriate use.
For business apps, we are generally tracking moments. For example, "when does this contract come into effect", "when was this employee hired", "when does the purchase of this house close". So LocalDateTime is not called for.
The two business scenarios for LocalDateTime are (a) making appointments where we want the moment to float if time zone rules change, such as clinic, salon, and studio bookings, and (b) where we mean several moments, each with the same wall-clock time but occurring at different points on the timeline, such as "Announce this corporate message at noon in each of our company factories in Delhi, Düsseldorf, and Detroit.". Search Stack Overflow to learn more on this, as I and others have posted multiple times already.
On Ideone.com, see some code I noodled around with in writing this Answer.
You need to use LocalTime#now(ZoneId zone) with ZoneOffset.UTC in order to get the local time at UTC; otherwise, the system picks up the local time of system's timezone.
Demo:
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit;
import java.util.concurrent.TimeUnit;
class Main {
public static void main(String[] args) {
Instant now = Instant.now();
var now1 = TimeUnit.SECONDS.convert(now.toEpochMilli(), TimeUnit.MILLISECONDS) - 60;
var now2 = TimeUnit.SECONDS.convert(now.minusSeconds(60).toEpochMilli(), TimeUnit.MILLISECONDS);
var now3 = LocalDateTime.now(ZoneOffset.UTC).minusSeconds(60).toEpochSecond(ZoneOffset.UTC);
var now4 = System.currentTimeMillis() / 1000 - 60;
System.out.println(now1);
System.out.println(now2);
System.out.println(now3);
System.out.println(now4);
}
}
Output from a sample run:
1674506413
1674506413
1674506413
1674506413
ONLINE DEMO
Learn more about the modern Date-Time API from Trail: Date Time.

How to store a Java Instant in a MySQL database

With Java Date objects the easiest way to go was to store them as MySql DateTime objects (in UTC). With the switch to Instant this approach won't work anymore because MySQL DateTime does not offer the precision to store nanoseconds. Just truncating them could lead to unexpected comparison results between a newly created Instant objects and the ones read from the database.
BigDecimal timestamps don't strike me as an elegant solution: writing select queries manually becomes more difficult because you have to convert the timestamp everywhere to make it readable, and the handling in Java is somewhat clunky compared to Instant or even Long values.
What's the best way to go here? Probably not varchar, right?
Truncate to microseconds
Obviously we cannot squeeze the nanoseconds resolution of an Instant into the microseconds resolution of the MySQL data types DateTime and Timestamp.
While I do not use MySQL, I imagine the JDBC driver is built to ignore the nanoseconds when receiving an Instant, truncating the value to microseconds. I suggest you try an experiment to see, and perhaps examine source code of your driver that complies with JDBC 4.2 and later.
Instant instant = Instant.now().with( ChronoField.NANO_OF_SECOND , 123_456_789L ) ; //Set the fractional second to a spefic number of nanoseconds.
myPreparedStatement.setObject( … , instant ) ;
…and…
Instant instant2 = myResultSet.getObject( … , Instant.class ) ;
The JDBC 4.2 spec requires support for OffsetDateTime but oddly does not require the two more commonly used types, Instant and ZonedDateTime. If your JDBC driver does not support Instant, convert.
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ; // Use `OffsetDateTime` if your JDBC driver does not support `Instant`.
Instant instant2 = odt.toInstant() ; // Convert from `OffsetDateTime` to `Instant`.
Then compare.
Boolean result = instant.equals( instant2 ) ;
System.out.println( "instant: " + instant + " equals instant2: = " + instant2 + " is: " + result ) ;
You wisely are concerned about values drawn from the database not matching the original value. One solution, if acceptable to your business problem, is to truncate any nanoseconds to microseconds in your original data. I recommend this approach generally.
The java.time classes offer a truncatedTo method. Pass a ChronoUnit enum object to specify the granularity. In this case, that would be ChronoUnit.MICROS.
Instant instant = Instant().now().truncatedTo( ChronoUnit.MICROS ) ;
Currently this approach should suffice as you are unlikely to have any nanoseconds in your data. Mainstream computers today do not sport hardware clocks capable of capturing nanoseconds, as far as I know.
Count from epoch
If you cannot afford to lose any nanosecond data that may be present, use a count-from-epoch.
I usually recommend against tracking date-time as a count from an epoch reference date. But you have few other choices in storing your nanosecond-based values in a database such as MySQL and Postgres limited to microsecond-based values.
Store pair of integers
Rather than using the extremely large number of nanoseconds since an epoch such as 1970-01-01T00:00Z, I suggest following the approach taken by the internals of the Instant class: Use a pair of numbers.
Store a number of whole seconds as an integer in your database. In a second column store as an integer the number of nanoseconds in the fractional second.
You can easily extract/inject these numbers from/to an Instant object. Only simple 64-bit long numbers are involved; no need for BigDecimal or BigInteger. I suppose you might be able to use a 32-bit integer column for at least one of the two numbers. But I would choose 64-bit integer column types for simplicity and for direct compatibility with the java.time.Instant class’ pair of longs.
long seconds = instant.getEpochSecond() ;
long nanos = instant.getNano() ;
…and…
Instant instant = Instant.ofEpochSecond( seconds , nanos ) ;
When sorting chronologically, you'll need to do a multi-level sort, sorting first on the whole seconds column and then sorting secondarily on the nanos fraction-of-second column.

Add a Double variable representing minute into a Date in Java

I have a Origin-Destination matrix representing the elapsed time between 2 point in minute. I wonder what is the best way to add the elapsed time to a Date.
Date clock;
SimpleDateFormat reqDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
clock = reqDF.parse(line[25]);
Double distance = distDB.find_distance(O, D, mode, facility_id);
Date current_time = clock + distance;
Does it makes more easier if I use a Calendar type instead of Date ?
Thanks
tl;dr
Instant.parse( "2016-12-23T01:23:45Z" )
.plusNanos( Math.round(
yourNumberOfMinutesAsDouble *
TimeUnit.MINUTES.toNanos( 1 ) )
)
Avoid old date-time classes.
Actually, you should using neither java.util.Date nor java.util.Calendar. These old legacy classes are notoriously troublesome, confusing, and flawed. Now supplanted by the java.time classes.
For the old classes, the Answer by Jireugi is correct. For java.time classes, read on.
Avoid using a fractional number for elapsed time
Not a good idea using a double or Double to represent elapsed time. Firstly, that type uses floating-point technology which trades away accuracy for speed of execution. So you will often have extraneous extra digits to the right of your decimal fraction.
Secondly, this is an awkward way to handle time, given that we have sixty seconds to a minute, and sixty minutes to an hour, and so on.
In Java, use the Period or Duration classes. See Oracle Tutorial.
In text, use the standard ISO 8601 format PnYnMnDTnHnMnS where P marks the beginning and T separates the years-months-days from the hours-minutes-seconds. So two and a half minutes would be PT2M30S.
Nanoseconds
If we must work with the Double as a number of minutes for elapsed time, let’s convert from your fractional decimal number to a whole number (integer).
Note that the old legacy date-time classes are limited to a resolution of milliseconds while the java.time classes can go as fine as nanoseconds. So we want to convert your Double to a whole number of nanoseconds.
Rather than hard-code a magic number of the number of nanoseconds in a minute for this calculation, let's use the TimeUnit enum. That class can calculate the number of nanoseconds in a minute for us ( 60 * 1_000_000_000L ).
Finally, the Math.round function returns the closest long to the argument, with ties rounding to positive infinity.
long nanoseconds = Math.round(
yourNumberOfMinutesAsDouble *
TimeUnit.MINUTES.toNanos( 1 )
);
Instant
If working with date-time values in UTC, use the Instant class. Each Instant represents a moment on the timeline in UTC with a resolution of nanoseconds.
Instant Instant.parse( "2016-12-23T01:23:45Z" )
Instant future = Instant.plusNanos( nanoseconds );
Duration
Rather than passing around a Double as your elapsed time, I strongly suggest you pass around Duration objects.
Duration duration = Duration.ofNanos( Math.round( yourNumberOfMinutesAsDouble * TimeUnit.MINUTES.toNanos( 1 ) ) );
You can do math with a Duration such as plus and minus.
Instant instant = Instant.parse( "2016-12-23T01:23:45Z" )
Instant future = instant.plus( duration );
You can generate a String representation of the Duration in standard ISO 8601 format such as PT8H6M12.345S by merely calling toString. And Duration can parse such strings as well.
String output = duration.toString(); // PT8H6M12.345S
…or going the other direction…
Duration duration = Duration.parse( "PT8H6M12.345S" );
You could try this using Math.round:
Date clock;
SimpleDateFormat reqDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
clock = reqDF.parse(line[25]);
Double distance = distDB.find_distance(O, D, mode, facility_id);
long clockTimeMs = clock.getTime();
long distTimeInMs = Math.round(distance * 60000);
Date current_time = new Date(clockTimeMs + distTimeInMs);
Here the Date gets converted into a milliseconds timestamp.
Since the distance is in minutes, you need to convert it also into milliseconds by multiplying it by 60 * 1000 (= 60000) before you can add it to the start time ("clock"). Finally a new Date gets created that represents the distance from the start time.
Please find details of the Date class here: https://docs.oracle.com/javase/6/docs/api/java/util/Date.html
If i understood your situation, you want to get current date, then using matrix [i, j] value (which is time - in minutes) you want to update the time to give an indication of - if you start from Origin (i), till what time you would reach to Destination (j).
I would rather use java's Calendar class. it gives you more flexibility. using 'Calendar' class, you can getTime(), which returns 'Date' type instance and then use this class to add/delete your time offset (there are methods provided by this class for such manipulations) and convert the 'Date' back to Calendar.

Current time in microseconds in java

On a Unix system, is there a way to get a timestamp with microsecond level accuracy in Java? Something like C's gettimeofday function.
No, Java doesn't have that ability.
It does have System.nanoTime(), but that just gives an offset from some previously known time. So whilst you can't take the absolute number from this, you can use it to measure nanosecond (or higher) precision.
Note that the JavaDoc says that whilst this provides nanosecond precision, that doesn't mean nanosecond accuracy. So take some suitably large modulus of the return value.
tl;dr
Java 9 and later: Up to nanoseconds resolution when capturing the current moment. That’s 9 digits of decimal fraction.
Instant.now()
2017-12-23T12:34:56.123456789Z
To limit to microseconds, truncate.
Instant // Represent a moment in UTC.
.now() // Capture the current moment. Returns a `Instant` object.
.truncatedTo( // Lop off the finer part of this moment.
ChronoUnit.MICROS // Granularity to which we are truncating.
) // Returns another `Instant` object rather than changing the original, per the immutable objects pattern.
2017-12-23T12:34:56.123456Z
In practice, you will see only microseconds captured with .now as contemporary conventional computer hardware clocks are not accurate in nanoseconds.
Details
The other Answers are somewhat outdated as of Java 8.
java.time
Java 8 and later comes with the java.time framework. These new classes supplant the flawed troublesome date-time classes shipped with the earliest versions of Java such as java.util.Date/.Calendar and java.text.SimpleDateFormat. The framework is defined by JSR 310, inspired by Joda-Time, extended by the ThreeTen-Extra project.
The classes in java.time resolve to nanoseconds, much finer than the milliseconds used by both the old date-time classes and by Joda-Time. And finer than the microseconds asked in the Question.
Clock Implementation
While the java.time classes support data representing values in nanoseconds, the classes do not yet generate values in nanoseconds. The now() methods use the same old clock implementation as the old date-time classes, System.currentTimeMillis(). We have the new Clock interface in java.time but the implementation for that interface is the same old milliseconds clock.
So you could format the textual representation of the result of ZonedDateTime.now( ZoneId.of( "America/Montreal" ) ) to see nine digits of a fractional second but only the first three digits will have numbers like this:
2017-12-23T12:34:56.789000000Z
New Clock In Java 9
The OpenJDK and Oracle implementations of Java 9 have a new default Clock implementation with finer granularity, up to the full nanosecond capability of the java.time classes.
See the OpenJDK issue, Increase the precision of the implementation of java.time.Clock.systemUTC(). That issue has been successfully implemented.
2017-12-23T12:34:56.123456789Z
On a MacBook Pro (Retina, 15-inch, Late 2013) with macOS Sierra, I get the current moment in microseconds (up to six digits of decimal fraction).
2017-12-23T12:34:56.123456Z
Hardware Clock
Remember that even with a new finer Clock implementation, your results may vary by computer. Java depends on the underlying computer hardware’s clock to know the current moment.
The resolution of the hardware clocks vary widely. For example, if a particular computer’s hardware clock supports only microseconds granularity, any generated date-time values will have only six digits of fractional second with the last three digits being zeros.
The accuracy of the hardware clocks vary widely. Just because a clock generates a value with several digits of decimal fraction of a second, those digits may be inaccurate, just approximations, adrift from actual time as might be read from an atomic clock. In other words, just because you see a bunch of digits to the right of the decimal mark does not mean you can trust the elapsed time between such readings to be true to that minute degree.
You can use System.nanoTime():
long start = System.nanoTime();
// do stuff
long end = System.nanoTime();
long microseconds = (end - start) / 1000;
to get time in nanoseconds but it is a strictly relative measure. It has no absolute meaning. It is only useful for comparing to other nano times to measure how long something took to do.
As other posters already indicated; your system clock is probably not synchronized up to microseconds to actual world time. Nonetheless are microsecond precision timestamps useful as a hybrid for both indicating current wall time, and measuring/profiling the duration of things.
I label all events/messages written to a log files using timestamps like "2012-10-21 19:13:45.267128". These convey both when it happened ("wall" time), and can also be used to measure the duration between this and the next event in the log file (relative difference in microseconds).
To achieve this, you need to link System.currentTimeMillis() with System.nanoTime() and work exclusively with System.nanoTime() from that moment forward. Example code:
/**
* Class to generate timestamps with microsecond precision
* For example: MicroTimestamp.INSTANCE.get() = "2012-10-21 19:13:45.267128"
*/
public enum MicroTimestamp
{ INSTANCE ;
private long startDate ;
private long startNanoseconds ;
private SimpleDateFormat dateFormat ;
private MicroTimestamp()
{ this.startDate = System.currentTimeMillis() ;
this.startNanoseconds = System.nanoTime() ;
this.dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS") ;
}
public String get()
{ long microSeconds = (System.nanoTime() - this.startNanoseconds) / 1000 ;
long date = this.startDate + (microSeconds/1000) ;
return this.dateFormat.format(date) + String.format("%03d", microSeconds % 1000) ;
}
}
You could maybe create a component that determines the offset between System.nanoTime() and System.currentTimeMillis() and effectively get nanoseconds since epoch.
public class TimerImpl implements Timer {
private final long offset;
private static long calculateOffset() {
final long nano = System.nanoTime();
final long nanoFromMilli = System.currentTimeMillis() * 1_000_000;
return nanoFromMilli - nano;
}
public TimerImpl() {
final int count = 500;
BigDecimal offsetSum = BigDecimal.ZERO;
for (int i = 0; i < count; i++) {
offsetSum = offsetSum.add(BigDecimal.valueOf(calculateOffset()));
}
offset = (offsetSum.divide(BigDecimal.valueOf(count))).longValue();
}
public long nowNano() {
return offset + System.nanoTime();
}
public long nowMicro() {
return (offset + System.nanoTime()) / 1000;
}
public long nowMilli() {
return System.currentTimeMillis();
}
}
Following test produces fairly good results on my machine.
final Timer timer = new TimerImpl();
while (true) {
System.out.println(timer.nowNano());
System.out.println(timer.nowMilli());
}
The difference seems to oscillate in range of +-3ms. I guess one could tweak the offset calculation a bit more.
1495065607202174413
1495065607203
1495065607202177574
1495065607203
...
1495065607372205730
1495065607370
1495065607372208890
1495065607370
...
Use Instant to compute microseconds since Epoch:
val instant = Instant.now();
val currentTimeMicros = instant.getEpochSecond() * 1000_000 + instant.getNano() / 1000;
a "quick and dirty" solution that I eventually went with:
TimeUnit.NANOSECONDS.toMicros(System.nanoTime());
UPDATE:
I originally went with System.nanoTime but then I found out it should only be used for elapsed time, I eventually changed my code to work with milliseconds or at some places use:
TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis());
but this will just add zeros at the end of the value (micros = millis * 1000)
Left this answer here as a "warning sign" in case someone else thinks of nanoTime :)
If you're interested in Linux:
If you fish out the source code to "currentTimeMillis()", you'll see that, on Linux, if you call this method, it gets a microsecond time back. However Java then truncates the microseconds and hands you back milliseconds. This is partly because Java has to be cross platform so providing methods specifically for Linux was a big no-no back in the day (remember that cruddy soft link support from 1.6 backwards?!). It's also because, whilst you clock can give you back microseconds in Linux, that doesn't necessarily mean it'll be good for checking the time. At microsecond levels, you need to know that NTP is not realigning your time and that your clock has not drifted too much during method calls.
This means, in theory, on Linux, you could write a JNI wrapper that is the same as the one in the System package, but not truncate the microseconds.
Java support microseconds through TimeUnit enum.
Here is the java doc:
Enum TimeUnit
You can get microseconds in java by this way:
long microsenconds = TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis());
You also can convert microseconds back to another time units, for example:
long seconds = TimeUnit.MICROSECONDS.toSeconds(microsenconds);
If you intend to use it for realtime system, perhaps java isnt the best choice to get the timestamp. But if youre going to use if for unique key, then Jason Smith's answer will do enough. But just in case, to anticipate 2 item end up getting the same timestamp (its possible if those 2 were processed almost simultaneously), you can loop until the last timestamp not equals with the current timestamp.
String timestamp = new String();
do {
timestamp = String.valueOf(MicroTimestamp.INSTANCE.get());
item.setTimestamp(timestamp);
} while(lasttimestamp.equals(timestamp));
lasttimestamp = item.getTimestamp();
LocalDateTime.now().truncatedTo(ChronoUnit.MICROS)
Here is an example of how to create an UnsignedLong current Timestamp:
UnsignedLong current = new UnsignedLong(new Timestamp(new Date().getTime()).getTime());

Sum two dates in Java

How can I add two dates in Java?
Example: The sum of "2010-01-14 19:16:17" "0000-10-03 01:10:05"
would result in "2010-11-17 20:26:22".
I know how to do it using Calendar and adding field by field.
Is any other way to sum them all (year/month/day/hour/minute/second) at once?
If you are using the Date object, you can just do:
Date d1 = ...
Date d2 = ...
long sum = d1.getTime() + d2.getTime();
Date sumDate = new Date(sum);
The code uses the .getTime() method that returns the number of milliseconds since the epoch.
Needless to say the Date class has a lot of problems and should be avoided when possible.
Do you want to sum other types instead?
Update: for Calendar, I would do the following (based on javadocs):
Calendar c1 = ...
Calendar c2 = ...
long sum = c1.getTimeInMillis() + c2.getTimeInMillis();
Calendar sumCalendar = (Calendar)c1.clone();
sumCalendar.setTimeInMillis(sum);
UPDATED: As Steve stated, this works if the Date you presented here assumes that the second date is with respect to the Java epoch. If you do want to start with year "0", then you need to account for that (by subtracting your epoch time).
Don't sum the time in millis of the two dates!
Date d1 = new Date();
Date d2 = new Date();
Date dTotal = new Date(d1.getTime() + d2.getTime());
System.out.println(dTotal); // Incorrect! Misses about 1970 years.
Just clone the Calendar and add the datetime parts one by one.
Calendar c1 = Calendar.getInstance();
Calendar c2 = Calendar.getInstance();
Calendar cTotal = (Calendar) c1.clone();
cTotal.add(Calendar.YEAR, c2.get(Calendar.YEAR));
cTotal.add(Calendar.MONTH, c2.get(Calendar.MONTH) + 1); // Months are zero-based!
cTotal.add(Calendar.DATE, c2.get(Calendar.DATE));
cTotal.add(Calendar.HOUR_OF_DAY, c2.get(Calendar.HOUR_OF_DAY));
cTotal.add(Calendar.MINUTE, c2.get(Calendar.MINUTE));
cTotal.add(Calendar.SECOND, c2.get(Calendar.SECOND));
cTotal.add(Calendar.MILLISECOND, c2.get(Calendar.MILLISECOND));
System.out.println(cTotal.getTime()); // Correct!
Needless to say, JodaTime is smarter and cleaner with this.
As always, I would recommend the Java 8 date/time APIs or Joda for date/time work, since they are much more powerful and intuitive.
You can add durations and periods to a DateTime object trivially. You can add minutes/seconds/months equally easily.
However, you can't add two dates directly, since that doesn't really make sense. This is a powerful illustration of why Joda is a help - it stops you doing stuff that you really shouldn't be doing.
tl;dr
LocalDateTime later =
LocalDateTime
.parse (
"2010-01-14 19:16:17"
.replace ( " " , "T" )
)
.plus( Period.parse ( "P10M3D" ) )
.plus( Duration.parse ( "PT1H10M5S" ) )
;
ISO 8601
The representation of a span-of-time using the same format as a moment is creating confusion. A span is not at all the same as a moment.
Instead of using YYYY-MM-DD HH-MM-SS format for a span of time, I suggest using the standard ISO 8601 format of PnYnMnDTnHnMnS. In this format, the P marks the beginning (for "Period" presumably) and the T separates the years-month-days portion from the hours-minutes-seconds portion.
Example values:
PT1H30M → One and a half hours.
P3Y6M4DT12H30M5S → Three years, six months, four days, twelve hours, thirty minutes, and five seconds.
P10M3DT1H10M5S → Your Question’s duration of 0000-10-03 01:10:05.
java.time
The Question and the other Answers use troublesome old date-time classes now outmoded by the java.time framework built into Java 8 and later. See Oracle Tutorial. Much of the java.time functionality has been back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP.
The java.time classes use ISO 8601 formats by default when parsing and generating Strings that represent date-time values.
The Question does not provide any time zone info, so here we use the LocalDateTime class. If we know an offset-from-UTC we would use the OffsetDateTime class, and if even better we knew a time zone, we would use the ZonedDateTime class.
Spans of time in java.time are divided amongst a pair of classes. Years-months-days are represented by the Period class, and hours-minutes-seconds are handled by the Duration class.
Combining these times, we can indeed perform date-time math. Here we add a span of time to an starting date-time to get a resulting date-time. And we do so in very few lines of code. The result is indeed that expected by the Question.
We convert the input strings to canonical ISO 8601 format by replacing the SPACE in the middle with a T.
LocalDateTime ldt = LocalDateTime.parse ( "2010-01-14 19:16:17".replace ( " " , "T" ) );
//"0000-10-03 01:10:05"
Period period = Period.parse ( "P10M3D" );
Duration duration = Duration.parse ( "PT1H10M5S" );
LocalDateTime result = ldt.plus ( period ).plus ( duration );
Compare to the result expected in the Question.
LocalDateTime expectation = LocalDateTime.parse ( "2010-11-17 20:26:22".replace ( " " , "T" ) );
Boolean isSame = result.equals ( expectation );
Dump to console.
System.out.println ( "ldt: " + ldt + " + period: " + period + " + duration: " + duration + " is result: " + result + " compared to expectation: " + expectation + " is the same: " + isSame );
ldt: 2010-01-14T19:16:17 + period: P10M3D + duration: PT1H10M5S is result: 2010-11-17T20:26:22 compared to expectation: 2010-11-17T20:26:22 is the same: true
You want to do getTimeInMillis() on both those Calendars so you'll have two honest-to-goodness long values you can add up. You can then take the sum and stash it in a new Calendar using that Calendar's setTimeInMillis() method.
Whether you want to add two Calendars as shown above or two Dates as shown in notnoop's answer is up to you, of course. The effect is similar, it just depends on what you want to do with the result. A Date is mostly just good for storing and/or converting to a String for printing out or displaying, whereas a Calendar will let you fiddle with the individual time values should you so choose.
As others have mentioned, you're committing some conceptual no-no's in using a Date or Calendar, which are meant to store "real" dates and times, e.g. ones in the 20th or 21st century, as intervals, i.e. time spans. The classes in the standard Java library don't give you really useful tools to handle this, which is why the Joda classes were developed. All the cool kids in date/time processing use those; but on the other hand that involves downloading and managing a 3rd party library.
notnoop answer is definitely correct. However, if you are going to do lots of processing of dates, times and intervals, I suggest that you look at class DateUtils in apache commons lang and at joda-time library.
JDK7 will come with better support for some of the features that joda-time provides. Just saying ... it might be a consideration if your app makes heavy usage of this stuff.
You need to define your EPOCH. The Java epoch (like Unix) is 1 Jan 1970 GMT/UTC. I assume you think you're adding ten months, 3 days and some odd hours from 1 Jan 0000 but you have a epoch offset until 1970. The maths may not necessarily work.
Use Calendar or Joda (as mentioned). If you just simply want to add a number of seconds and days (&c) then feel free to add said # of milliseconds to your first date object.
Use calendar class add method to add two dates in java.
Calendar calendar=Calendar.getInstance();
calendar.add(Calendar.Date,23);
calendar.add(Calendar.Month,13);
calendar.add(Calendar.Year,15);
By using add method in Calendar class we can add day,month,year to the existing date.
click here for complete program.
I am occasionally guilty of this practice too, storing time interval in a date object and using getTime() as suggested by notnoop.
It works. Contrary to certain opinion, it certainly works. I just ignore that the interval could be representative of an unintended date. It is a quick and dirty way for me to add an interval, say, [6 years, 6 months, 6 days, 6 hours, 6 minutes, 6 seconds] to a date.

Categories