How can I retrieve the difference between two Date instances in minutes? - java

According to the Talend docs, it is possible to calculate the difference between two dates using TalendDate.dateDiffFloor up to seconds and milliseconds.
However, the docs don't say how (or which format parameter has to be specified).
I have to get this value in seconds as it will feed into a tInfiniteLoop component.
I have tried with "mmmm" and "mm" with no luck. In that case I get the error:
Exception in component tMap_3
java.lang.RuntimeException: Can't support the dateType: mm ,please try "yyyy" or "MM"
at routines.TalendDate.diffDateFloor(TalendDate.java:661)
at timeouttester.job_2_0_1.job_2.tInfiniteLoop_2Process(job_2.java:1156)
at timeouttester.job_2_0_1.job_2.runJobInTOS(job_2.java:1616)
at timeouttester.job_2_0_1.job_2.main(job_2.java:1464)
Which argument do I have to specify to get minutes? And, if not doable, maybe there is a workaround doing this in "vanilla" Java if not possible via Talend?
I am currently using the following statement in a tMap component:
TalendDate.diffDateFloor(TalendDate.parseDateInUTC("EEE, d MMM yyyy HH:mm:ss", Var.expires), TalendDate.getCurrentDate(), "mmmm")

I have no clue about Talend but as you said vanilla is also possible for you: You may use the class Duration which represents the duration between two objects of type Temporal. Such a temporal class would, for example, be Instant which is a snapshot on the time line. Instant has great support in the API. You can retrieve one from Date#toInstant, or from Calendar#toInstant and more.
See this small example:
Date dateBefore = new GregorianCalendar(2014, Calendar.FEBRUARY, 11).getTime();
Instant before = dateBefore.toInstant();
Instant now = Instant.now();
Duration duration = Duration.between(before, now);
System.out.println("Days: " + duration.toDays());
However, If I'm not mistaken the class Instant itself is only precise down to milliseconds. If that is not enough, you may use another class which implements Temporal or create your own.
For your application, you are probably interested in:
Duration#toMinutes()
Duration#toMillis()
Note that the returned value (long) of those methods are rounded downwards (floor). So if the real amount of minutes where something like 1.453, toMinutes() will return 1 and toMillis() returns 1453.

Related

How to convert seconds to java.sql.Timestamp?

I needed to truncate milliseconds to seconds and implemented it in this way:
private static Long millisToSeconds(Long millisValue) {
return TimeUnit.MILLISECONDS.toSeconds(millisValue);
}
So now it truncates millis as expected, for example:
Long secondsValue = millisToSeconds(1554052265830L);
System.out.println("millisToSeconds ---> " + toSeconds);
// Prints millisToSeconds ---> 1554052265
But then I want to convert secondsValue to java.sql.Timestamp but the following implementation results in an error:
java.lang.IllegalArgumentException: Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]
What should I fix in my implementation to convert seconds to timestamp so that the resulting timestamp looks like 2019-03-31 11:45:06 ?
java.time
I am assuming that you are asking for a java.sql.Timestamp for use with your SQL database. In most cases you shouldn’t ask for that. The Timestamp class is poorly designed and long outdated, and a modern JDBC driver or JPA implementation will be happy to accept a type from java.time, the modern Java date and time API, instead.
long millisValue = 1_554_052_265_830L;
Instant i = Instant.ofEpochMilli(millisValue);
i = i.truncatedTo(ChronoUnit.SECONDS);
System.out.println(i);
2019-03-31T17:11:05Z
I don’t know why you wanted to truncate to seconds, but you can see that it has been done (or it’s easy to leave that line out).
Some JDBC drivers accept an Instant directly when you pass it to PreparedStatement.setObject (one of the overloaded versions of that method) even though the JDBC specification doesn’t require this. If yours doesn’t, use an OffsetDateTime instead. Convert like this:
OffsetDateTime odt = i.atOffset(ZoneOffset.UTC);
System.out.println(odt);
2019-03-31T17:11:05Z
You can see that the value is still the same, only the type is different.
What should I fix in my implementation to convert seconds to timestamp
so that the resulting timestamp looks like 2019-03-31 11:45:06 ?
First, as I said, you should fix your code not to require a Timestamp, but also you are asking the impossible. As far as I know, Timestamp.toString would always produce at least one decimal on the seconds, so it would at least look like 2019-03-31 11:45:06.0.
If you do indispensably need a Timestamp for a legacy API that you cannot or don’t want to change just now, convert the Instant from before:
Timestamp ts = Timestamp.from(i);
System.out.println(ts);
2019-03-31 19:11:05.0
Don’t be fooled by the time looking different (19:11 instead of 17:11). Timestamp prints in my local time zone, which is Europe/Copenhagen, 2 hours ahead of UTC since summer time (DST) began on March 31. So we have still got the same point in time.
Link: Oracle tutorial: Date Time explaining how to use java.time.
You can use SimpleDateFormatto format the date as per your requirement. See below
Long secondsValue = millisToSeconds(1554052265830L);
System.out.println("millisToSeconds ---> " + secondsValue);
Timestamp timeStamp = new Timestamp(secondsValue);
String formattedDate = new SimpleDateFormat("yyyy-mm-dd hh:mm:ss").format(timeStamp.getTime());
System.out.println(formattedDate);
The error suggest that you are using Timestamp.valueOf(String) (possibly with secondsValue.toString() as the argument?).
A java.sql.Timestamp is a special version of java.util.Date with nanosecond precision to serialize/deserialize SQL TIMESTAMP values. It is not a second value at all.
The constructor of Timestamp take a millisecond value, not a second value (for nanosecond precision, you need to use the separate setNanos with the sub-second nanoseconds).
In any case the proper way would be to use:
long milliseconds = ...;
long seconds = TimeUnit.MILLISECONDS.toSeconds(milliseconds);
long truncatedMilliseconds = TimeUnit.SECONDS.toMillis(seconds);
// or truncatedMilliseconds = (milliseconds / 1000) * 1000;
Timestamp value = new Timestamp(truncatedMilliseconds);
However, since you are talking about needing a specific string format, I'm not sure you need this at all. Unless you are using JDBC to store this value in a database, you should not be using java.sql.Timestamp at all (and even when using JDBC, then it would probably be better to use java.time.LocalDatetime instead).

System.currentTimeMillis() not displaying time in UTC , instead displaying current timezone time

I have a requirement of getting UTC time , hence in many places iam using below code for calcualting utc time.
System.currentTimeMillis() ;
Iam in IST - (GMT+5:30) , System.currentTimeMillis() - should display UTC time (IST-5:30) , instead it is taking current time (GMT+5:30).
I donot want to use the Apache of joda date and time api. i want to use the Java api itslef. Help me in resolve my issue.
System.currentTimeMillis() just returns a long - that's not in any sort of date format.
If you're actually using:
Date date = new Date(System.currentTimeMillis());
System.out.println(date);
then you're just seeing the result of Date.toString(), which always uses the system default time zone.
Use DateFormat (e.g. SimpleDateFormat) to specify the calendar system (typically Gregorian), time zone and format you want to use. For example:
Date date = ...;
DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss",
Locale.US);
format.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
String result = format.format(date);
As an aside, I'd strongly recommend abstracting the idea of "getting the current time" into an interface which you implement in one case using System.currentTimeMillis() (or equivalently, just new Date()) but implement for testing purposes with a value you can set and update at will. Then inject this "clock" interface into anything which needs to access the current date/time. It makes it much easier to test time-based components.
(I'd also strongly recommend using Joda Time or the java.time package from Java 8 if you possibly can. I know you've said you don't want to, but I suspect that's because you haven't spent as much time swearing at java.util.Date and java.util.Calendar as some of us. Both of those alternatives will lead to much cleaner code which is much easier to read and reason about. If you're trying to avoid a one-time hit of getting Joda Time into your build process, weigh that against the amount of time you're likely to spend maintaining your code. Or just update to Java 8... Java 7 will be out of free-update support soon anyway...)

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.

Joda Interval losing timezone information

I am defining a Joda interval as follows:
final DateTimeZone fromDtz = DateTimeZone.forID("Europe/Paris");
final DateTime fromDt = DateTime.parse("2013-08-08T01:02:03+0200").withZone(fromDtz);
final DateTimeZone toDtz = DateTimeZone.forID("Europe/London");
final DateTime toDt = DateTime.parse("2013-08-08T01:02:05+0100").withZone(toDtz);
final Interval interval = new Interval(fromDt, toDt);
However it appears that I lose the information on the timezone for the end of the interval. If I do a simple toString() on the interval I receive:
2013-08-08T01:02:03.000+02:00/2013-08-08T02:02:05.000+02:00
which is missing some of the information I'm trying to retain (the specific timezone of the datetime at the end of the interval).
I've wandered through the documentation and source code and it appears that Interval only contains a single chronology. Is there a way to tell Joda to keep both timezones without manually carting around two separate DateTimes?
Fundamentally an interval is the time between two instants - and instants don't have chronologies, time zones etc. They're just points on a universal time line - a number of milliseconds since an epoch. The fact that ReadableInterval exposes getChronology at all is a design flaw, IMO - but there really is only one such chronology. If you're trying to keep more information than that, I believe you'll need to use your own type.
It may be as simple as a start/end pair and a toInterval() method for places where you really want to use the Joda Time Interval methods, but I don't think there's anything built into Joda Time to do what you want.
try using withZoneRetainFields()

How to store and retrieve milliseconds in a date object in Java?

I'm making a basic Java program that reads in a subtitle (.srt) file and I would like to store each time as a Date object. I really only need to keep track of Hours, minutes, seconds, and milliseconds (to 3 digits). I think I am able to store it using this:
String start = "00:01:01,604";
DateFormat sdf = new SimpleDateFormat("hh:mm:ss,SSS");
Date startDate = sdf.parse(start);
For retrieving, I can do something like this:
return String.format("\nStart: %d:%d:%dText: %s\n", startDate.getHours(),startDate.getMinutes(), startDate.getSeconds(), text);
I'm looking for something that would do something similar to getMilliseconds (if it existed). Thank you very much!
What you're handling is not a date! Don't use the Date class to handle it! Dates have strange extra rules that you don't care about and that could easily trip you up (just think of leap years, leap seconds and time zones).
You should either
use a long to hold the milliseconds and handle the calculation on your own (it's not so hard, you're not implementing a calendar) or
use an existing duration class such as the one from Joda Time.
The recommended way to get access to part of date (hours,minutes, etc.) in Java is now using Calendar.get(Calendar.MILISECONDS), see javadocs. In case of your code it would look like this:
Date startDate = sdf.parse(start);
Calendar calendar = Calendar.getInstance();
calendar.setTime(startDate);
int milliseconds = calendar.get(Calendar.MILISECONDS);
P.S. Please note that regarding to javadocs Date.getHours(),Date.getSeconds(), etc. methods are currently deprecated anyway. Don't use them :).
Just call date.getTime() and get milliseconds.
You can always use Date.getTime() for getting value in milliseconds. It will return a value in long format

Categories