converting timestamp to nanoseconds - java

I have a certain value of date and time say 28-3-2012(date) - 10:36:45(time) . I wish to convert this whole timestamp to nanoseconds with the precision of nanoseconds. As in the user would input the time and date as shown but internally i have to be accurate upto nanoseconds and convert the whole thing to nanoseconds to form a unique key assigned to a specific object created at that particular time.
Could some one please help me with the same..

The precision of the sample date is seconds, the representation in long format is a value in millisecond units. You can convert that to nanosecond units by multiplying it with 1,000,000.
But, in fact, it will simply append nine zeros to the oririginal date value and not add any extra information that you'd need to create hashvalues. A Date object has no "hidden" nanosecond precision.
Java offers the method System.nanoTime() which returns a timevalue in nano second units. But we can't wrap it in a Date object without loosing precision. Nevertheless, it may help in your case to create unique "time values".

if you have Date object:
long nanosecond = date.getTime() * 1000000;
or you can parse your time string if its look like (dd/MM/yyyy HH:mm:ss)
DateFormat df = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
Date date = df.parse(dateString);
long nanosecond = date.getTime() * 1000000;

I suppose the simplest way would be to use JDK's support for this. Try following
TimeUnit.NANOSECONDS.toNanos(duration)
Here the single parameter duration will be the long value to which you want to convert to NanoSeconds.
Hope this helps.

Related

Cannot convert from java Double to java Date

I am having an issue with converting a double to a Java date object in the format: yyyy-MM-dd HH:mm:ss
I have tried to convert this double value to a long value then instanciate a Date object with the result, but I got errors saying that I cannot convert from double to long.
my timestamp double values are in this format:
1.511554592277516E9
Can anybody help me with this issue please, thanks in advance.
Assuming that this floating point value is seconds past the Unix Epoch of 1 Jan 1970 0:00 GMT, this will provide a conversion to a LocalDateTime with that offset:
LocalDateTime localDateTime = LocalDateTime.ofEpochSecond(
Double.valueOf(1.511554592277516E9).longValue(), 0, ZoneOffset.UTC);
System.out.println(localDateTime);
I leave converting this to a Date as an exercise for the reader.
Your floating-point value, 1.511554592277516E9, no doubt denotes seconds since the epoch of January 1, 1970 at midnight UTC, with microsecond precision: 1 511 554 592 seconds and 277 516 microseconds (millionths of a second).
I suggest using java.time, the modern Java date and time API also known as JSR-310, for this. It is much nicer to work with than the outdated Date class and friends, and also offers nanosecond precision (Date only has millisecond precision, so you would lose precision if converting into one). More specifically I will first create a java.time.Instant object (conversion to other date-time types will be easy, I’ll touch on one example at the end).
Getting the full precision through into an Instant requires a little thought. I played a little with double and long, but realized (1) double doesn’t have the full precision required, the nanoseconds will not be right (2) converting to a long holding the nanoseconds (not the only way, but certainly the easiest) will create a “year 2262 problem”, so if you are handling dates in a far future, it will not work. In any case, I think that the easy and safe solution is to use BigDecimal for the math required before feeding the numbers into an Instant.
String secondsSinceEpoch = "1.511554592277516E9";
BigDecimal decimalSeconds = new BigDecimal(secondsSinceEpoch);
long seconds = decimalSeconds.longValue();
long nanos = decimalSeconds.subtract(BigDecimal.valueOf(seconds))
.movePointRight(9)
.longValueExact();
Instant inst = Instant.ofEpochSecond(seconds, nanos);
System.out.println(inst);
This prints:
2017-11-24T20:16:32.277516Z
The printed date-time is in UTC. If the value is as expected, I should say it confirms that your floating-point value was indeed seconds since the epoch.
You requested a date-time in the format yyyy-MM-dd HH:mm:ss. You will need to decide in which time zone you want the date-time. Date objects don’t have a format, so you will also need to get the format in a string. For example:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println(inst.atZone(ZoneId.of("America/Vancouver")).format(formatter));
This prints
2017-11-24 12:16:32
You substitute your desired time zone, of course. atZone() converts the Instant into a ZonedDateTime, another often used class of java.time.
EDIT: In case you don’t want to bother with BigDecimal, you accept a slight inaccuracy and/or your receive your value as a double rather than a string, here’s an alternative in fewer lines of code:
double secondsSinceEpoch = 1.511554592277516E9;
long longSeconds = (long) secondsSinceEpoch;
long micros = Math.round((secondsSinceEpoch - longSeconds) * 1_000_000);
Instant inst = Instant.ofEpochSecond(longSeconds).plus(micros , ChronoUnit.MICROS);
In this particular case it gives exactly the same result, down to the nanosecond. I’m not sure whether with other inputs, the microseconds may end up inaccurate, but on the other hand, if you receive a double (not a string), there’s nothing you could do about that anyway.

Writing and reading LocalDateTime from file most efficiently

What is the fastest way to write LocalDateTime instance to file and then read it from file and convert it back to LocalDateTime object?
I used to save milliseconds and then convert it to Date object. It looked pretty fast but now I am dealing with Java 8's LocalDateTime and it's not clear what would be most efficient way to save and retrieve it from file.
I don't think using DateTimeFormater is a good idea as it requires more resources to convert it to String and then parse the String.
Time zone is not relevant.
If you want to save the milliseconds and timezone is not important, you can use the java.time.Instant class - with only the LocalDateTime there's no way to get the milliseconds, because this class has no timezone/offset information.
// get the current date
Instant instant = Instant.now();
// get milliseconds (equivalent to java.util.Date.getTime())
long millis = instant.toEpochMilli();
// get Instant from milliseconds
Instant instant = Instant.ofEpochMilli(millis);
If you have a LocalDateTime, though, you can easily convert it to an Instant:
LocalDateTime d = LocalDateTime.now();
Instant instant = d.atOffset(ZoneOffset.UTC).toInstant();
This code obviously assumes that the values in the LocalDateTime correspond to an UTC date and time. To convert the Instant back to a LocalDateTime:
LocalDateTime d = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
PS: have you measured your system's performance to know if "fast" is really an issue? Anyway, I'm doing things the "standard" way (the most straightforward way based on what the API offers), is that what you want?
Maybe you can think that creating an Instant as an "intermediary" object makes things less "fast" (but you'll need to measure that anyway). If that's the case, you can get the millis from the LocalDateTime directly (assuming that it corresponds to a date and time in UTC):
// get the current date
LocalDateTime d = LocalDateTime.now();
// get milliseconds value
long millis = d.toEpochSecond(ZoneOffset.UTC) * 1000 + d.get(ChronoField.MILLI_OF_SECOND);
// get LocalDateTime from millis
LocalDateTime d = LocalDateTime.ofEpochSecond(millis / 1000, (int) (millis % 1000) * 1000000, ZoneOffset.UTC);
It's important to note that java.time classes have nanoseconds precision, so getting the milliseconds makes you lose this precision.
If you don't want to lose the nanoseconds precision and don't necessarily need to work with the millis value, you can store 2 different numbers (epoch day and nano of day):
// get the current date
LocalDateTime d = LocalDateTime.now();
// get values from LocalDateTime
long epochDay = d.toLocalDate().toEpochDay();
long nanoOfDay = d.toLocalTime().toNanoOfDay();
// save both values to file
// retrieve the LocalDateTime from the values
LocalDateTime d = LocalDateTime.of(LocalDate.ofEpochDay(epochDay), LocalTime.ofNanoOfDay(nanoOfDay));
This doesn't require the conversion to UTC, but it requires 2 numbers instead of one. You might think that creating a LocalDate and a LocalTime makes things slower, but these 2 objects are always created internally by LocalDateTime (in all cases).
Not sure, though, if all this math is "faster" enough than using an Instant. It's a matter of testing to see which one is best for your case.
But for me, the most "efficient" in terms of clarity and code-easy-to-maintain is using an Instant (or using the last approach of epoch day and nano of day). And unless you're dealing with millions of records, I'm not sure if that'll really be a performance issue.
I've made a simple test (run each case above 10 million times), and the last approach (using epoch day and nano of day) seems to be the fastest. But the difference is less than 1 second. Only by running 2 billion times I've got a 20-seconds difference, so if you're dealing with this many records, maybe it's worth it.
Regarding other resources (memory usage, CPU, I/O), I didn't check. But anyway, performance issues are very specific to each environment: depending on how the system is designed, how the system's parts/modules/components interact with each other, and many other factors, you can have different bottlenecks in each situation.
In the end, you'll have to test each approach and see which one performs best in your system. Or you can conclude that it doesn't make a significant difference (and for cases with less than a couple of millions records, maybe it doesn't - but you'll only know after benchmarking it).

How to get the time difference of different timezone?

I am trying to get the difference between the current time and the time which is stored in DB.
I tried below code but its not giving the correct result since java.lang.System.currentTimeMillis() returns
UTC time whereas we save date to our application in EST format.
Code :
java.lang.System.currentTimeMillis() - emp.getModifiedDate()
Could you please suggest me a correct way to do it ?It will be very helpful for me
Thanks
System.currentTimeMillis() returns the number of milliseconds since January 1, 1970 UTC. It is time-zone agnostic.
If you are storing the time in the database as millis then simply subtracting the two numbers will give you the correct difference.
If you are storing the time in some other way (e.g. as a String), you can parse it (e.g. with SimpleDateFormat) to take into account the time zone and then obtain a Date from which you can obtain the millis.
Hope this helps! This will give you difference in no of days.
Date date1 = new Date();
long diff = date1.getTime() - emp.getModifiedDate().getTime();
System.out.println((int) (diff) / (1000 * 60 * 60 * 24)));
For more read this

From jFreeChart Millisecond to java.util.Date

Regarding jFreeChart's Millisecond,
How can I get a java.util.Date object from a Millisecond instance?
From the docs, it only seems possible to subtract the milliseconds within Millisecond.
Since a Millisecond object is constructed like so:
Millisecond ms = new Millisecond(
millisec,
second,
minute,
hour,
day,
month,
year);
I should be able to extract a valid Date object as well.
Edit
I need a Date object that gives back the exact time up to the millisecond accurate.
Does .getStart() provide this?
[ANSWER]: YES
Millisecond is like any other RegularTimePeriod in JFreeChart, so you can just
Date d = ms.getStart();
or
Date d = ms.getEnd();
depending on whether you want a date referring to the beginning or the end of your millisecond (same value either way).
See The JFreeChart API for more info.
EDIT: Adding code here since comments kill formatting:
Millisecond ms = new Millisecond();
System.out.println(ms.getStart().getTime());
System.out.println(ms.getEnd().getTime());
will print the same millisecond twice.
As far as I can see the Millisecond Class represents the time period of a millisecond and I'd assume the the getStart and getEnd Methods inherited from RegularTimePeriod return (nearly) the same Date of which one is one you're looking for.
(my answer was late) Perhaps you could use this code:
java.util.Date date = new java.util.Date(freeMillis.getMillisecond());
edit: scrap that, freeMillis.getMillisecond() returns just a millisecond part.

How to reformat the time of Java Time class

I searched topics about formatting time but these were all about Date class or DateTime. I am working with Time class. I created time as:
Time time = new Time(Time.getCurrentTimezone()) ;
time.setToNow();
String berkay = time.toString();
System.out.println(berkay);
When I execute it the output is :
20130417T070525GMT(3,106,0,0,1366182325)
actually date and time is correct (2013-04-17 07:05:25)
but I need to convert it into : 20130417070525 (My reason to do this is I will search database according to date so it is easier to compare times in that format)
How can I convert it?
Try this:
Time time = new Time(System.currentTimeMillis()) ;
SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
String date = df.format(time).toString();
System.out.println(date);
EDIT
But as smttsp suggested its much more efficient to store it as timestamp
To convert java.util.Date into String you should consider java.text.SimpleDateFormat.
For using java.util.Date as a parameter of a database query you should pass the Date as is without converting it into any other format.
passing Date parameter to create date range query
<- In the answer there is sample how to create such query.
It is a bit late but if you are working on time and you need to compare or sort, the best way is to use Unix timestamp. It starts from 1-Jan-1970 00:00:00 and increments 1 each second.
It is a long value(64 bit) which is quite efficient to use in both time and space. Here is the website for Unix timestamp conversion.
Also 20130417070525 is 14 char string(at least 15 byte, I guess) and 1366182325 is long(8 byte). So go for long value. U can get it in that way
Date myDate = new Date(); // current time
myDate.getTime(); // converts it to specified format.

Categories