how to convert timestamp(in microseconds) string to date in Java/Scala.
My goal is to compare two timestamps and find the differences between them.
I'm using java 8 and example Timestamp string is 1474457086337977.
I would like to convert this into Date or Timestamp instance.
tl;dr
Instant.EPOCH.plus(
Duration.ofNanos(
TimeUnit.MICROSECONDS.toNanos(
Long.parse( "1474457086337977" ) ) ) )
java.time
The java.time classes support a resolution of nanoseconds, more than enough for your microseconds.
Parsing a string of a number
Parse the string as a long to get a count of microseconds from the epoch.
long micros = Long.parse( "1474457086337977" );
And of course you can always use an integer literal. Note the L appended to integer literal.
long micros = 1_474_457_086_337_977L ;
Converting a long into Instant
We want to transform that count of microseconds from the epoch of beginning of 1970 in UTC (1970-01-01T00:00:00Z) into an Instant. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds. That means up to nine digits of a decimal fraction.
The Instant class has handy static methods for converting from a count of whole seconds, from a count of whole seconds plus a fractional second in nanoseconds, or from a count of milliseconds. But unfortunately no such methods for a count of microseconds or nanoseconds.
As a workaround, we can define a Duration and add it to the epoch reference date already defined as a constant. We can instantiate a Duration as a number of nanoseconds. To get nanoseconds, we multiply your microseconds by a thousand. Note the use of 64-bit long rather than 32-bit int.
Duration duration = Duration.ofNanos( micros * 1_000L );
Instant instant = Instant.EPOCH.plus( duration );
instant.toString(): 2016-09-21T11:24:46.337977Z
Alternatively, you can use the TimeUnit enum to convert microseconds to nanoseconds without hard-coding a “magic number”.
Duration duration = Duration.ofNanos( TimeUnit.MICROSECONDS.toNanos( micros ) );
To adjust into other offsets or time zones, search StackOverflow for Java classes OffsetDateTime or ZonedDateTime.
Converting to legacy date-time types
You should avoid the old date-time types bundled with the earliest versions of Java. They have proven to be poorly-designed, confusing, and troublesome. Now supplanted by the java.time types.
But if you must interact with old code not yet updated to the java.time types, you may convert to/from java.time. Look to new methods added to the old classes.
java.sql.Timestamp ts = java.sql.Timestamp.from( instant );
Beware of data loss when converting from a java.time type to java.util.Date or java.util.Calendar. These types resolve to only milliseconds. A truncation from nanoseconds to milliseconds is performed silently, lopping off those last six (of nine) possible digits of a fractional second.
java.util.Date utilDate = java.util.Date.from( instant ); // Caution: Data loss in truncating nanoseconds to milliseconds.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old date-time classes such as java.util.Date, .Calendar, & java.text.SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to java.time.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations.
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP (see How to use…).
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time.
Well, what about converting those microseconds to milliseconds and then just create a timestamp object?
long microsecs = 1474457086337977L;
long millis = TimeUnit.MILLISECONDS.convert(microsecs, TimeUnit.MICROSECONDS);
Timestamp time = new Timestamp(millis);
Wouldn't that work?
--Edit
To address the comments left in the answer:
About Java 8's new Date Time API
First, since you mention that you're using Java 8 I totally agree that a better approach would be to use the new Java 8 Date/Time API. However, this is a luxury you don't always have even when working with Java 8 because you may still be interacting with an old API still using the old Java Date/Time classes, or simply because the rest of your API still uses them and you don't want to start mixing things.
It is not clear in your question if you already know this, you seem to be sure that you want to use either java.util.Date or java.sql.Timestamp and I didn't question that, I just worked around the parameters of your question.
Clearly the new Java date/time APIs are much better than the old ones, but there are millions of lines of code out there still using the old APIs and they work. Yet again I thought that was out of the scope of the answer and it seems you already have other good answers here to address that.
About Possible Data Loss
One comment mentions that the answer might run into data loss. I think in Java all integer arithmetic is subject to potential underflow or overflow. My mistake is probably not have mentioned it.
It is true that TimeUnit.convert method might end up causing overflows or underflows in certain scenarios. It is documented in the method.
A nanosecond is one billionth of a second (1/1000000000)
A microsecond is one millionth of a second (1/1000000).
A millisecond is one thousandth of a second (1/1000)
Which means that, once expressed as a long, a millisecond number should be a much smaller number than a microsecond one, right?
The formula used by TimeUnit.convert is as follows
final long MICROS = 1000000L;
final long MILLIS = 1000L;
long microsecs = 1474457086337977L;
long millisecs = microsecs / (MICROS / MILLIS)
Which means you would run into data loss only if your microseconds are really small numbers e.g. if you had less than 1,000 microseconds. You should validate your code never goes into a scenario like this.
One comment left in this answer argues that the right answer should probably use nanoseconds, but then again a nanosecond long value would be a much bigger number than your microseconds and so, during conversions to nanoseconds you might still run into overflows.
For example, think what would happen if you had Long.MAX_VALUE microseconds, how could you convert that to nanoseconds using just Java long arithmetic without an overflow given that nanoseconds are supposed to be a much bigger number than your Long.MAX_VALUE microseconds?
My point being that regardless of you using Java 8 Date Time or legacy Java Date Time APIs you need a long value representing an instant in the time line, but that long has limitations in regards to how far in the past or how far in the future you can go, and when you do conversions between units, that arithmetic is subject to underflow and overflow and there's no way around it and you should be aware of that to avoid very nasty bugs.
Once more, I thought that was a given and outside the scope of the question and I bring it up only because I got some downvotes for this omission.
You can try following code, which will take time stamp as a string:
BigInteger b = new BigInteger("1474457086337977");
b=b.divide(new BigInteger("1000"));
String x =b.toString();
DateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
long milliSeconds= Long.parseLong(x);
System.out.println(milliSeconds);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(milliSeconds);
System.out.println(formatter.format(calendar.getTime()));
Or for more accuracy, you can use BigDecimal:
BigDecimal b = new BigDecimal("1474457086337977");
b=b.divide(new BigDecimal("1000"));
String x =b.toString();
Related
Hi I read some article about new java.time package.And some of articles say we shouldnt use java.util.Date family.We can use offsetDateTime or LocalDateTime instead of java.util.Date.
And I am wondering about what should we use instead of Timestamp in new java.time package?
As I check Timestamp use
public class Timestamp extends java.util.Date
There are two types of time spans in Java 8:
Period - represents time difference between two points in years, months, days
Duration - represents a time duration - the actual physical time-span, doesn't depend on what is the start time
For example 1 month "period" will be 30 days in April, 31 in may, so the values might be calculated differently in different contexts. Also time zone changes (daylight saving) are taken into account. Duration of certain number of seconds, minutes, hours, days, will not depend on the context. For example 30 days will always be 30 days.
You have a good description in the doc:
https://docs.oracle.com/javase/tutorial/datetime/iso/period.html
Timestamp equivalent
I am assuming that you are referring to the outdated java.sql.Timestamp and/or to the timestamp (without time zone) and timestamp with time zone datatypes of SQL. The first was designed for use with the last two. The answer is different for the two.
For a timestamp in SQL timestamp with time zone is clearly recommended since it actually unambiguously defines a point in time, which is in the definition of what a timestamp is. For a timestamp with time zone you should use the java.time class that you already mentioned, OffsetDateTime. Some JDBC drivers and JPA implementations will accept Instant too.
In most SQL dialects a mere timestamp is a date and time of day with high resolution (for example microseconds) without time zone. Lacking time zone it does not define a point in time, so calling it a timestamp is really a lie. In any case the corresponding java.time type is the other class you mentioned, LocalDateTime.
All of the mentioned java.time classes have resolution of nanoseconds. I know of no SQL dialect that would demand more than that.
You are fully correct. Not only is java.util.Date poorly designed and long outdated. Timestamp is a true hack on top of that class. I recommend you don’t use any of them.
Timespan equivalent
Artur Olszak in another answer has already nicely given the basis of Period and Duration. There is no need for me to repeat that. As a supplement, please be aware that even though Duration has methods for converting to and from a number of days, it isn’t really well suited for days since it assumes that a day is always 24 hours, which is not always the case because of summer time (DST) and other anomalies. As soon as you need to count days, I recommend either Period or a simple number of days.
Links
Wikipedia article: Timestamp.
My answer to a related quetsion about retrieving an SQL timestamp into a java.time type.
just a question what i am doing wrong. I have this code:
public static int berechneSekundenwert(String datum, String zeit) throws ParseException {
Date dt = new Date();
SimpleDateFormat df = new SimpleDateFormat( "dd.MM.yyyy HH:mm:ss" );
dt = df.parse( datum+" "+ zeit);
int gesamtzeit = (int)dt.getTime();
return gesamtzeit;
}
Now my import format is:
09.11.2019 01:30:17
What i want to do is calculate the time passed for these dates, so i
can later sort them by time. But i get negative values?!
Example output (passed time, date, daytime):
-2120215336 30.09.2019 12:03:35
1757321960 25.09.2019 16:06:25
-2111322336 30.09.2019 14:31:48
-1281127040 21.08.2019 12:05:36
-1280681040 21.08.2019 12:13:02
377782960 09.09.2019 16:54:06
1301386664 09.11.2019 01:30:17
710621960 13.09.2019 13:21:25
712564960 13.09.2019 13:53:48
Shouldn't they all be positive, since java states, that the getTime function measures the time since 01.01.1970
Anyone knows what i did wrong?
Computers use something called a timestamp to represent dates. In Java, Date::getTime() returns the milliseconds passed since 1970-01-01T00:00:00.000Z up to the date in question as long (64-bit integer).
In the code presented, this value is narrowed down to an int (32-bit integer). By narrowing the long to an int, the highest 32 bits get cut of. The largest value representable by an int is 2^31 - 1. A quick calculation shows that:
(2^31 - 1) (milliseconds)
/ 1000 (milliseconds per second)
/ 60 (seconds per minute)#
/ 60 (minutes per hour)
/ 24 (hours per day)
= 24.8551348032 (days)
This means that after roughly 25 days, the int will overflow (as it is defined in the Two's compliment). Not to mention that a later point in time could have a lower value than an earlier point in time, thus the negative values.
To fix this issue1, I would suggest to define gesamtzeit as long.
Two remarks on your code:
java.util.Date is regarded as outdated. I would suggest to use java.time.Instant instead.
I would suggest to use English in the source code, only exception being you use domain-specific words that cannot (well) be translated to English.
1 This is only a temporary fix. All representation with a fixed number of bits will eventually overflow. In fact, all representation with any memory constraint at all will overflow eventually. I leave it up to the reader to find out when a 64-bit integer will overflow
tl;dr
See correct Answer by Turing85 about 32-bit versus 64-bit integers.
Use only modern java.time classes, never Date/SimpleDateFormat.
Consider the crucial issue of time zone or offset-from-UTC.
Educate the publisher of your data about the importance of (a) including zone/offset info, and (b) using ISO 8601 standard formats.
Code:
LocalDateTime.parse(
"09.11.2019 01:30:17" ,
DateTimeFormatter.ofPattern( "dd.MM.uuuu HH:mm:ss" )
)
.atOffset(
ZoneOffset.UTC
)
.toInstant()
.toEpochMilli()
See this code run live at IdeOne.com.
1573263017000
Details
The correct Answer by Turing85 addresses your specific question as to why the invalid negative numbers. But you have other problems.
ISO 8601
Now my import format is: 09.11.2019 01:30:17
I suggest you educate the publisher of this data about the ISO 8601 standard defining formats to use when communicating date-time values as text.
Legacy date-time classes
You are use terrible date-time classes that were supplanted years ago by the modern java.time classes defined in JSR 310. Never use Date or SimpleDateFormat.
Moment
Apparently you want to get a count of milliseconds since the epoch reference of first moment of 1970 in UTC. But doing that requires a moment, a specific point on the timeline.
Your input does not meet this requirement. Your input is a date and a time-of-day but lacks the context of an offset-from-UTC or a time zone.
So, take your example of 09.11.2019 01:30:17. We cannot know if this is 1:30 in the afternoon of Tokyo Japan, or 1:30 PM in Paris France, or 1:30 in Toledo Ohio US — which are all very different moments, several hours apart on the timeline.
So we must first parse your input as a LocalDateTime. This class represent a date and time without any concept of offset or zone.
String input = "09.11.2019 01:30:17" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd.MM.uuuu HH:mm:ss" ) ;
LocalDateTime ldt = LocalDateTime.parse( input , f ) ;
Perhaps you know for certain the offset or zone intended by the publisher of this data. If so:
Suggest to the publisher of this data that they include the zone/offset info within their data.
Apply a ZoneOffset to get an OffsetDateTime, or a ZoneId to get a ZonedDateTime.
Perhaps you know for certain this input was intended for UTC, that is, an offset of zero hours-minutes-seconds.
OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC ) ;
To get a count of milliseconds since 1970-01-01T00:00Z convert to the basic building-block class Instant.
Instant instant = odt.toInstant() ;
Interrogate for a count of milliseconds since epoch.
long millisSinceEpoch = instant.toEpochMilli() ;
Understand that your original code ignored the crucial issue of time zone & offset-from-UTC. So your code implicitly applies the JVM's current default time zone. This means your results will vary at runtime, and means you likely have incorrect results too.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
why you downcast the return value ofgetTime()?
just make you method return long instead of int
and replace this line
int gesamtzeit = (int)dt.getTime();
with
long gesamtzeit = dt.getTime();
I have read all of the other Q/A about Date Manipulation, but none of them seems to deliver a satisfactory answer to my concern.
I have a project with geographically diverse users which uses Date in some of its classes and data. The thing is that I am looking for an efficient way to manipulate the Dates for the different users in their respective timezone, most of the answers suggest using Joda library for Date manipulation, which quite don't understand yet because I still have not found any operation you cannot do with traditional Java, so if someone can explain what can I do with Joda that can't be done with traditional Java, then I may consider using it.
I finally came to the approach of using System.currentTimeMillis() to save my dates into the database (any database). This would avoid me to worry about what timezone is using the database to store the dates. If I want to query the database for an specific date or range of dates, I would perform the queries using the long value of the Date I want to query:
SELECT * FROM table1 WHERE date1>=1476653369000
And when retrieving a ResultSet I would then format the long value retrieved from database to a readable Date using the timezone of the user requesting the data.
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(resultSet.getLong(1));
cal.setTimeZone(TimeZone.getTimeZone("Asia/Calcutta"));
Date myDate = cal.getTime();
According to some opinions I have read, some people say emphatically that storing System.currentTimeMillis() is definitely not the best practice, nevertheless, for some reason they all miss to say WHY it is not recommendable. Am I missing something? Does this cause a performance issue for the conversions Long->Date/Date->Long? Is there any use case that cannot be accomplished when using Long instead Date in database? Can someone post a rationale explanation about this?
In the other hand, assuming that I keep using Date values to store dates in database, is there a way to avoid worrying about time-zones while handling database Date?
Thanks in advance.
I have read all of the other Q/A about Date Manipulation
No, you certainly did not read them all.
You would have learned that both the legacy date-time classes (such as java.util.Date & java.util.Calendar) and the Joda-Time project are supplanted by the java.time classes (1,890 results for search on 'java.time').
You would have learned not to track date-time values as a count-from-epoch. Debugging and logging becomes very difficult with bugs going undiscovered as humans cannot decipher the meaning of a long integer as a date-time. And because many granularities of counting (whole seconds, milliseconds, microseconds, nanoseconds, whole days, and more) and at least a couple dozen of epochs are employed in various software projects create ambiguity about your data with assumptions leading to errors, misinterpretation, and confusion.
You would have learned to use date-time types in your database to track date-time values.
You would have learned to work and store date-time values in UTC. Adjust into a time zone only where required by logic or as expected by the user for presentation. “Think global, present local.”
You would have learned that while a valiant industry-first effort, the legacy date-time classes are poorly designed, confusing, and troublesome. See What's wrong with Java Date & Time API? for some discussion. Joda-Time was the first good date-time library in the industry, and inspired its replacement, the java.time classes built into Java 8 and later.
I'll be somewhat brief as all of this has been covered many times already on Stack Overflow.
Work in UTC. In Java that means the Instant class is commonly used. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
Instant instant = Instant.now();
Any serious database such as Postgres tracks date-time values in UTC. Your JDBC driver handles the detail of converting from database internally-stored data to a Java type. JDBC drivers that comply with JDBC 4.2 and later can directly handle java.time types via PreparedStatement::setObject & ResultSet::getObject methods.
myPreparedStatement.setObject( … , instant );
For non-compliant drivers, fall back to using java.sql types such as java.sql.Timestamp to communicate with database, and convert to/from java.time types via new methods added to the old classes. The internal details of how the database handles date-time values may be quite different than how java.time does. For the most part the JDBC driver hides all the nitty-gritty details from you. But one critical issue is resolution, which you should study in your database. The java.time classes handle date-times with a resolution up to nanoseconds but your database may not. For example, Postgres uses a resolution of microseconds. So going back-and-forth means data-loss. You want to use the truncation methods on the java.time classes to match your database.
myPreparedStatement.setTimestamp( … , java.sql.Timestamp.from( instant ) );
So, no time zone involved. So no “worrying about time-zones while handling database Date”.
When you want to see the same moment through the lens of a region’s wall-clock time, apply a ZoneId to get a ZonedDateTime.
ZoneId z = ZoneId.of( "Asia/Kolkata" );
ZonedDateTime zdt = instant.atZone( z );
When taking a zoned date-time back to the database, extract an Instant.
Instant instant = zdt.toInstant();
Be aware that for any given moment, the date as well as the time-of-day varies around the globe by time zone. So if an exact moment matters, such as when a contract expires, beware of using a date-only value. Either use a date-time value for the exact moment, or store the intended time zone alongside the date-only so the exact moment can be calculated later.
LocalDate ld = LocalDate.of( 2016, 1 , 1 );
// Determine the first moment of 2016-01-01 as it happens in Kolkata.
ZonedDateTime zdt = ld.atStartOfDay( ZoneId.of( "Asia/Kolkata" ) );
Instant instant = zdt.toInstant(); // Adjust to UTC and store.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, .Calendar, & java.text.SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to java.time.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8 and SE 9 and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
what can I do with Joda that can't be done with traditional Java
It's not really about what you can or cannot do with traditional Java in the general case. It's more about how the library API works to make you write better (more robust and correct) code easier than traditional Java does.
So much so that as of Java 8 the Joda API was more or less copied/adopted verbatim with just package names changed and incorporated into the Java 8 SE standard library.
Therefore if you are using Java 8 you should pick the new API, and if not you should consider that using Joda will at least buy you a smooth path towards upgrading/porting to Java 8 when you are able to.
A few examples:
Consistent API for date and time types.
Date/time objects are immutable, manipulations return new instances of the type representing the altered value. (Like Java Strings). This makes it easier to reason about reuse of date/time objects.
By design avoids mixing DST & timezone dependent values/operations with DST & timezone agnostic ones. This makes it a lot easier to write code that works consistently and correctly and doesn't have corner cases dependent on timezone/locale/date/time-of-day.
Sane defaults for things like toString() so serialising/deserialising can be expected to work correctly with minimal effort.
Culture/locale dependent corner cases and things you weren't aware of yet (for example, did you know about the traditional Korean calendar?) which saves you a whole lot of hassle when converting your date times between locales/calendaring systems. Also: a wealth of formatting options.
The concept of Instants to represent 'absolute' time stamps which is useful when working with geographically distributed systems (when the system default clocks/timezones & DST rules may differ) or for interop because it uses UTC.
EDIT to add:
According to some opinions I have read, some people say emphatically that storing System.currentTimeMillis() is definitely not the best practice, nevertheless, for some reason they all miss to say WHY it is not recommendable. Am I missing something?
System.currentTimeMillis() has a few downsides. The big drawback is that the type of clock is ill defined. It could be a monotonic clock, it could be clock subject to DST and timezone or it could be a UTC time. It is also not necessarily an accurate clock, it is not actually guaranteed to be accurate down to the millisecond. Just whatever happens to be to hand for something that will work as a semblance of the current time at the current time, basically.
This means that if you want to use multiple servers to handle incoming requests, for instance, it gets tricky when you have to consider working with the output of System.currentTimeMillis() from server A in the context of your program running on a different server B the next day, say.
Just like the title says, I've been able to isolate from a text file a string containing a duration in the format of "HH:mm:ss." How would I go about converting it to a duration? I need to convert it to a double that expresses this timestamp in terms of 1 hour, so if it's "08:30:00" I need the double to have a value of 8.5. Not sure exactly how to go about converting it, seems that time is a tricky subject in Java. Any help would be greatly appreciated, even if it's just you saying "use this class" so I can look it up and figure it out.
Thanks!
You can split the expression into parts then parse and calculate duration:
String[] a = "08:30:00".split(":");
double d = Integer.parseInt(a[0]) + Integer.parseInt(a[1]) / 60.0;
tl;dr
Duration.between (
LocalTime.MIN ,
LocalTime.parse ( "08:30:00" )
).toString()
PT8H30M
Duration vs Timestamp
If by the string 08:30:00 you mean "eight and a half hours" span of time, then do not use the term "timestamp". The word “duration” is correct and commonly used. And avoid that format of HH:MM:SS because it is so ambiguous, appearing to be a time-of-day. Instead use the standard format discussed below.
If by the string 08:30:00 you mean “half-past eight in the morning”, then use the word 'timestamp' and avoid the term 'duration'.
These are two very different concepts. You must get clear on them, each should be distinct in your mind. Using the ambiguous format of HH:MM:SS makes that distinction all the more difficult (so avoid that format!).
java.time
The modern way is with the java.time classes.
LocalTime
As mentioned in the comment by Sharma, first parse your string as a LocalTime. This class represents a time-of-day without a date and without a time zone. Having no time zone means these objects are based on a generic 24-hour clock without regard for anomalies such as Daylight Saving Time (DST).
We do not really want a LocalTime as your input string represents a span of time rather than a time-of-day. But this is just the first step.
LocalTime lt = LocalTime.parse ( "08:30:00" );
Duration
To represent the desired span-of-time, we want the Duration class. This class is for spans of time not attached to the timeline. We can create one by converting that LocalTime via getting the amount of time from the beginning of the time-of-day clock, 00:00:00.0 or LocalTime.MIN, and the lt we just instantiated.
Duration d = Duration.between ( LocalTime.MIN , lt );
ISO 8601
We can see the result by generating a String in standard ISO 8601 format for durations by simply calling Duration::toString. The java.time classes use ISO 8601 by default when parsing/generating strings. For durations, the standard format is PnYnMnDTnHnMnS where the P marks the beginning and the T separates the years-months-days portion from the hours-minutes-seconds portion. So, our eight-and-a-half hours will appear as PT8H30M.
System.out.println ( "d.toString(): " + d );
d.toString(): PT8H30M
Avoid decimal numbers for date-time values
For handling such duration values, I strongly suggest using the Duration object in your Java code and the ISO 8601 format when serializing to text.
Using objects in your code provides type-safety, makes your code more self-documenting, and ensures valid values.
Using ISO 8601 format for text makes for values that can easily be parsed, is a format easily read by humans, and is unambiguous in its meaning unlike 08:30:00 which can be misread as a time-of-day.
Your desired format of a decimal number like 8.5 is ambiguous (easy to lose track of its meaning). Also a decimal number is awkward and often incorrect when using a floating-point type (float, Float, double, Double) as these types generate extraneous incorrect digits at the far end of the decimal fraction. Floating-point technology purposely trades away accuracy to gain speed of execution.
BigDecimal
If you must use a fractional number, and want accuracy, use the BigDecimal class.
In this example, I assume you want hours and minutes while truncating any fractional minute. So I call toMinutes on the Duration.
BigDecimal minutesPerHour = new BigDecimal ( 60L ); // Use var/constant for clarity of your intent.
BigDecimal minutes = new BigDecimal ( d.toMinutes () );
BigDecimal fractionalHours = minutes.divide ( minutesPerHour );
frationalHours.toString(): 8.5
See this example code live in IdeOne.com.
You might want to use BigDecimal facility for rounding if you insist on using these decimals rather than Duration objects and ISO 8601 text.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8 and SE 9 and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
I would use String.split() to accomplish this. That will split it into an array based on the regex/separators that you specify in the parameters. Something like this,
String time = "08:30:00";
String[] splitValues = time.split(":");
double hour = splitValue[0];
double minute = splitValue[1];
double seconds = splitValue[2];
You could then add up the values. You know that there are 60 minutes in an hour, and 60 seconds in a minute. You could convert these to hours by dividing by 60 and 3600, respectively. Then, it's just a simple matter of addition.
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());