Convert UTC date into milliseconds - java

I am not interested in what the current UTC time is in milliseconds, nor do I need to mess with timezones. My original date is already stored as a UTC timestamp.
I have a date stored in a database in UTC time, "2012-06-14 05:01:25".
I am not interested in the datetime, but just the date portion of the it. So, after retrieving the date in Java, and excluding the hours, minutes, and seconds - I am left with "2012-06-14".
How can I convert this into UTC milliseconds?

EDIT: I'd missed the "ignoring the time of day" part. It's now present, but near the end...
The simplest approach is probably to use SimpleDateFormat, having set the time zone appropriately:
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
format.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = format.parse(text);
long millis = date.getTime();
(Setting the time zone is the important bit here, as otherwise it will interpret the value to be in the local time zone.)
Alternatively, if you're doing anything less trivial than this, use Joda Time which is a much better date/time API. In particular, SimpleDateFormat isn't thread-safe whereas DateTimeFormatter is:
// This can be reused freely across threads after construction.
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")
.withLocale(Locale.US)
.withZoneUTC();
// Option 1
DateTime datetime = formatter.parseDateTime(text);
long millis = dateTime.getMillis();
// Option 2, more direct, but harder to diagnose errors
long millis = formatter.parseMillis(text);
Now so far, we've parsed the whole whole caboodle. The easiest way of ignoring the date part is just to round it off - after all, Java doesn't observe leap seconds, so we can just truncate it:
long millisPerDay = 24L * 60L * 60L * 1000L; // Or use TimeUnit
long dayMillis = (millis / millisPerDay) * millisPerDay;
That will "round towards 1970" so if you have a date before 1970 it will round to the end of the day - but I suspect that's unlikely to be a problem.
With the Joda Time version you could just use this instead:
DateTime dateTime = formatter.parseDateTime(text);
long millis = dateTime.toLocalDate().getLocalMillis();
I would personally not go with the idea of just taking a substring. Even though you're not actually interested in preserving the hour/minute/second, I think it's appropriate to parse what you've been given and then throw away information. Aside from anything else, it makes your code fail appropriately with bad data, e.g.
"2012-06-100"
or
"2012-06-14 25:01:25"
indicate problems in whatever's supplying you data, and it's good to spot that rather than to continue blindly just because the first 10 characters are okay.

UPDATE: See the modern solution using java.time classes in the correct Answer by Ole V.V..
Simpler
The answer by Jon Skeet is correct. And he makes a good point about including, rather than truncating, the time-of-day info while parsing.
However, his code could be simplified. Especially so because Joda-Time gained an important new method in the latest versions: withTimeAtStartOfDay. This method supplants all the "midnight"-related classes and methods which are now deprecated.
Specifying a Locale is a good habit, as shown in his code. But in this particular case a Locale is not necessary.
His answer correctly suggests the Joda-Time library, far superior to using java.util.Date, .Calendar, and java.text.SimpleTextFormat. Those classes are notoriously troublesome, and should be avoided. Instead use either Joda-Time or the new java.time package built into Java 8 (inspired by Joda-Time, defined by JSR 310).
First Moment Of The Day
You cannot ignore time-of-day if what you want is a count of milliseconds-since-epoch. I suspect what you want is to change the time to first moment of the day. In UTC, this always means the time 00:00:00.000. But note that in local time zones, the first moment may be a different time because of Daylight Saving Time and possibly other anomalies.
ISO 8601
Your string is nearly in standard ISO 8601 format, but we need to swap a T for the SPACE in the middle. Then we can feed the resulting string directly to Joda-Time as Joda-Time has built-in formatters used by default for standard strings.
Example Code
The following example code assumes the intent of your question is to parse a string as a date-time value in UTC time zone, adjust the time to the first moment of the day, and then convert to number of milliseconds since Unix epoch (beginning of 1970 in UTC).
String inputRaw = "2012-06-14 05:01:25";
String input = inputRaw.replace( " ", "T" ); // Replace SPACE with a 'T'.
DateTime dateTime = new DateTime( input, DateTimeZone.UTC ); // Parse, assuming UTC.
DateTime dateTimeTopOfTheDay = dateTime.withTimeAtStartOfDay(); // Adjust to first moment of the day.
long millisecondsSinceUnixEpoch = dateTimeTopOfTheDay.getMillis(); // Convert to millis. Use a 'long', not an 'int'.

java.time and JDBC 4.2
I am providing the modern answer. These days (and for the last several years) you should use java.time, the modern Java date and time API, for your date and time work. And since JDBC 4.2 you can directly retrieve java.time objects from your database (and also store them into it). A modern JPA implementation (Hibernate at least since Hibernate 5) will be happy to do the same. So forget about SimpleDateFormat, Date and other old classes used in most of the old answers. The mentioned ones are poorly designed, and java.time is so much nicer to work with.
Retrieve proper date-time objects from your database
I also recommend that you don’t retrieve your UTC time as a string from the database. If the datatype in SQL is timestamp with time zone (recommended for UTC times), retrieve an OffsetDateTime. For example:
PreparedStatement pStmt = yourDatabaseConnection
.prepareStatement("select utc_time from your_table where id = 7;");
ResultSet rs = pStmt.executeQuery();
if (rs.next()) {
OffsetDateTime utcDateTime = rs.getObject("utc_time", OffsetDateTime.class);
long millisecondsSinceEpoch = utcDateTime.truncatedTo(ChronoUnit.DAYS)
.toInstant()
.toEpochMilli();
System.out.println("Milliseconds since the epoch: " + millisecondsSinceEpoch);
}
If the type in SQL is dateTime or timestamp without time zone, we probably need to retrieve a LocalDateTime instead (details depending on your JDBC driver and the time zone of your database session). It goes in the same manner. For converting your LocalDateTime to OffsetDateTime, see the conversion below.
If you need to convert from a string
If you cannot avoid getting your UTC time as a string as in the question, parse it into a LocalDateTime and convert from there. For example:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
String utcTimeString = "2012-06-14 05:01:25";
long millisecondsSinceEpoch = LocalDateTime.parse(utcTimeString, formatter)
.atOffset(ZoneOffset.UTC)
.toInstant()
.toEpochMilli();
System.out.println("Milliseconds since the epoch: " + millisecondsSinceEpoch);
Output:
Milliseconds since the epoch: 1339650085000
Link
Oracle tutorial: Date Time explaining how to use java.time.

Use the Date object in combination with SimpleDateFormat.
There is a method named getTime() in Date which will return the milliseconds for you.
Example that solves your problem :
Date truc = new SimpleDateFormat( "y-m-d").parse( "2010-06-14");
System.out.println(truc.getTime());

SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd"); //or whatever format you have
Date t = ft.parse('2014-03-20');
String result = String.format("%tQ", t);
System.out.printf("%tQ", t);
There are two methods here:
you put the result milliseconds into a variable result
printing it straight off.

I use a simple and straight forward approach:
Date date = new Date(utcDateInString);
long utcDateInMilliSeconds = date.getTime();

Related

Converting java.sql.Timestamp to Instant Time

From my database i retrieve value as :
20-DEC-17 10.15.53.000000000 AM
I want above java.sql.Timestamp to be converted to Instant time as :
2017-12-20T10:15:53Z
I tried following with current time stamp
Timestamp ts2 = new Timestamp(date1.getTime());
Date tradeDate1=new Date(ts2.getTime());
Instant tradeInstant = tradeDate1.toInstant();
System.out.println("Tade Instant"+ tradeInstant);
Actual time stamp: Fri Jun 22 16:07:35 IST 2018
What is prints in instan : Tade Instant2018-06-22T10:37:35.420Z
The hours/mins/seconds are updated which I dont want - is there a way this can be retained as is?
I am assuming that you are using at least Java 8 and at least JDBC 4.2. I am further assuming that the timestamp doesn’t have time zone or offset information in the database, but is to be understood as a timestamp in UTC (which is a recommended practice). In this case I would consider it safest to add the information about UTC offset explicitly in Java:
PreparedStatement yourPreparedStatement
= yourConnection.prepareStatement("select trade_timestamp from your_table");
ResultSet rs = yourPreparedStatement.executeQuery();
while (rs.next()) {
LocalDateTime tradeDateTime = rs.getObject(1, LocalDateTime.class);
Instant tradeInstant = tradeDateTime.atOffset(ZoneOffset.UTC).toInstant();
System.out.println("Trade Instant: " + tradeInstant);
}
Note that the code avoids the outdated Timestamp class completely. A LocalDateTime is a date and time of day without time zone or offset. If your database datatype had been timestamp with time zone, you could have passed either Instant.class or OffsetDateTime.class to rs.getObject and have got an Instant or an OffsetDateTime back. JDBC 4.2 only specifies support for OffsetDateTime, but many drivers support Instant too. Obviously with Instant you need no further conversion. With OffsetDateTime do
Instant tradeInstant = tradeDateTime.toInstant();
Depending on your database and its capabilities it is also possible that you can set UTC as offset/time zone on the database session so you can get the correct instant even from timestamp without time zone.
Discussion: Arvind Kumar Avinash in a comment recommends that one should rely only on the types officially supported by JDBC 4.2, that is, LocalDateTime and OffsetDateTime for our purposes. The types are mentioned at the bottom of the article Why do we need a new date and time library? on Oracle’s web site, there’s a link at the bottom. Arvind Kumar Avinash further refers us to PSQLException: Can't infer the SQL type to use for an instance of java.time.Instant, also linked to at the bottom. Since comments are fragile, I wanted to include the essence here in the answer.
What went wrong in your code?
It seems your database session understood the timestamp as a date and time in your local time zone (IST, I assume it’s for India Standard Time (other interpretations exist)). According to Mark Rotteveel’s informative comment this behaviour is required by JDBC, but it doesn’t agree with your need when the value is in UTC. Therefore it gave you the wrong point in time, though it looked right when you printed it. The conversion in itself was correct.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Why do we need a new date and time library?
PSQLException: Can't infer the SQL type to use for an instance of java.time.Instant. on doobie’s GitHub page (doobie is a JDBC layer for Scala)
Building from the comment about not using SimpleDateFormat, I have moved to DateTimeFormatter:
Date today = new Date();
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss") // same format
.withLocale(Locale.UK) // UK locale
.withZone(ZoneId.systemDefault());
String output = dateTimeFormatter.format( today.toInstant() );
System.out.println( output );
Running gives you:
2018-06-22T14:14:26
I have created a SimpleDateFormat, which only prints "up to seconds":
/* simple date format */
DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
/* get toInstant() and convert to date */
Date myDate = Date.from(today.toInstant());
/* myDate formatted using DATE_FORMAT */
String formattedDate = DATE_FORMAT.format(myDate);
System.out.println(formattedDate);

How to print the current time and date in ISO date format in java?

I am supposed to send the current date and time in ISO format as given below:
'2018-02-09T13:30:00.000-05:00'
I have written the following code:
Date date = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm");
SimpleDateFormat formatter1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.000'Z'");
System.out.println(formatter.format(date));
System.out.println(formatter1.format(date));
It prints in the following way:
2018-04-30T12:02
2018-04-30T12:02:58.000Z
But it is not printing as the format mentioned above. How can I get the -5:00 as shown in the format and what does it indicate?
In java 8 you can use the new java.time api:
OffsetDateTime now = OffsetDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE_TIME;
System.out.println(formatter.format(now)); // e.g. 2018-04-30T08:43:41.4746758+02:00
The above uses the standard ISO data time formatter. You can also truncate to milliseconds with:
OffsetDateTime now = OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS);
Which yields something like (only 3 digits after the dot):
2018-04-30T08:54:54.238+02:00
Easy solution:
System.out.println(OffsetDateTime.now(ZoneId.of("America/Panama")).toString());
Just now I got this output:
2018-04-30T02:12:46.442185-05:00
To control that seconds are always printed with exactly three decimals:
DateTimeFormatter formatter
= DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSXXX");
OffsetDateTime now = OffsetDateTime.now(ZoneId.of("America/Panama"));
System.out.println(now.format(formatter));
2018-04-30T02:12:46.442-05:00
The first, the easy version will print enough groups of three decimals to render the full precision. It will also leave out the seconds completely if they happen to be 0.0. Both are probably OK because all of this is allowed within the ISO 8601 format that you asked for. So whoever receives the string should be happy anyway.
Please fill in your desired time zone where I used America/Panama. It’s best to give explicit time zone for predictable output.
I am using and recommending java.time, the modern Java date and time API. The SimpleDateFormat that you used is not only long outdated, it is also notoriously troublesome. java.time is so much nicer to work with.
What does -05:00 indicate?
-05:00 is an offset from UTC (or GMT, it is nearly the same thing). So your example string is probably from eastern time zone in North America or some other place in Central or Southern America (Cuba, Bolivia, to mention a few that use this offset for some of the year). More precisely -05:00 means that we’re using a clock that is 5 hours (and 0 minutes) behind UTC. So 2:12:46-05:00 denotes the same point in time as 7:12:46 UTC. If we only knew the time was 2:12:46 and didn’t know a time zone or offset, it would be very ambiguous. An offset is perfect for turning the time into an unambiguous point in time.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Wikipedia article: ISO 8601
Wikipedia article: UTC offset

DateTime Manipulation in C# vs Java

I'm new to Java. I have a time I am getting from a web-page, this is in the "hh:mm" format (not 24 hour). This comes to me as a string. I then want to combine this string with todays date in order to make a Java Date I can use.
In C#:
string s = "5:45 PM";
DateTime d;
DateTime.TryParse(s, out d);
in Java I have attempted:
String s = "5:45 PM";
Date d = new Date(); // Which instantiates with the current date/time.
String[] arr = s.split(" ");
boolean isPm = arr[1].compareToIgnoreCase("PM") == 0;
arr = arr[0].split(":");
int hours = Integer.parseInt(arr[0]);
d.setHours(isPm ? hours + 12 : hours);
d.setMinutes(Integer.parseInt(arr[1]));
d.setSeconds(0);
Is there a better way to achieve what I want?
Is there a better way to achieve what I want?
Absolutely - in both .NET and in Java, in fact. In .NET I'd (in a biased way) recommend using Noda Time so you can represent just a time of day as a LocalTime, parsing precisely the pattern you expect.
In Java 8 you can do the same thing with java.time.LocalTime:
import java.time.*;
import java.time.format.*;
public class Test {
public static void main(String[] args) {
String text = "5:45 PM";
DateTimeFormatter format = DateTimeFormatter.ofPattern("h:mm a");
LocalTime time = LocalTime.parse(text, format);
System.out.println(time);
}
}
Once you've parsed the text you've got into an appropriate type, you can combine it with other types. For example, to get a ZonedDateTime in the system time zone, using today's date and the specified time of day, you might use:
ZonedDateTime zoned = ZonedDateTime.now().with(time);
That uses the system time zone and clock by default, making it hard to test - I'd recommend passing in a Clock for testability.
(The same sort of thing is available in Noda Time, but slightly differently. Let me know if you need details.)
I would strongly recommend against using java.util.Date, which just represents an instant in time and has an awful API.
The key points here are:
Parse the text with a well-specified format
Parse the text into a type that represents the information it conveys: a time of day
Combine that value with another value which should also be carefully specified (in terms of clock and time zone)
All of these will lead to clear, reliable, testable code. (And the existing .NET code doesn't meet any of those bullet points, IMO.)
To parse the time, you can do as explained in #Jon Skeet's answer:
String input = "5:45 PM";
DateTimeFormatter parser = DateTimeFormatter.ofPattern("h:mm a", Locale.ENGLISH);
LocalTime time = LocalTime.parse(input, parser);
Note that I also used a java.util.Locale because if you don't specify it, it'll use the system's default locale - and some locales can use different symbols for AM/PM field. Using an explicit locale avoids this corner-case (and the default locale can also be changed, even at runtime, so it's better to use an explicit one).
To combine with the today's date, you'll need a java.time.LocalDate (to get the date) and combine with the LocalTime, to get a LocalDateTime:
// combine with today's date
LocalDateTime combined = LocalDate.now().atTime(time);
Then you can format the LocalDateTime using another formatter:
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm");
System.out.println(combined.format(fmt));
The output is:
16/08/2017 17:45
If you want to convert the LocalDateTime to a java.util.Date, you must take care of some details.
A java.util.Date represents the number of milliseconds since 1970-01-01T00:00Z (aka Unix Epoch). It's an instant (a specific point in time). Check this article for more info.
So, the same Date object can represent different dates or times, depending on where you are: think that, right now, at this moment, everybody in the world are in the same instant (the same number of milliseconds since 1970-01-01T00:00Z), but the local date and time is different in each part of the world.
A LocalDateTime represents this concept of "local": it's a date (day, month and year) and a time (hour, minute, second and nanosecond), but without any relation to a specific timezone.
The same LocalDateTime object can represent different instants in time in different timezones. So, to convert it to a Date, you must define in what timezone you want it.
One option is to use the system's default timezone:
// convert to system's default timezone
ZonedDateTime atDefaultTimezone = combined.atZone(ZoneId.systemDefault());
// convert to java.util.Date
Date date = Date.from(atDefaultTimezone.toInstant());
But the default can vary from system/environment, and can also be changed, even at runtime. To not depend on that and have more control over it, you can use an explicit zone:
// convert to a specific timezone
ZonedDateTime zdt = combined.atZone(ZoneId.of("Europe/London"));
// convert to java.util.Date
Date date = Date.from(zdt.toInstant());
Note that I used Europe/London. The API uses IANA timezones names (always in the format Region/City, like America/Sao_Paulo or Europe/Berlin).
Avoid using the 3-letter abbreviations (like CST or PST) because they are ambiguous and not standard.
You can get a list of available timezones (and choose the one that fits best your system) by calling ZoneId.getAvailableZoneIds().
And there's also the corner cases of Daylight Saving Time (when a LocalDateTime can exist twice or can't exist due to overlaps and gaps). In this case, Jon's solution using ZonedDateTime avoids this problem).

How to check a date (in UTC format) is 48 hours before today date [duplicate]

This question already has answers here:
How to check if a date Object equals yesterday?
(9 answers)
Closed 8 years ago.
I tried to convert the new today's date object to UTC. But no luck since new date object is always in local time zone. I have been trying to verify two dates using 'before' method. date1 is in UTC format. date2 is today.
The below code always prints the today's date object in local time zone.
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
public class test {
/**
* #param args
*/
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
String todayStr = sdf.format(new Date());// This string is in UTC. But I need date object in UTC.
try {
System.out.println(sdf.parse(todayStr));// This is still printing in local time zone.
} catch (ParseException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
A Date object isn't in any time zone - it's just a wrapper around the number of milliseconds since the Unix epoch. The Unix epoch is typically described in terms of UTC (namely midnight at the start of January 1st 1970) but it's really just a point in time.
To get the point in time 48 hours before "now", you can use something like:
Date earlier = new Date(System.currentTimeMillis() - TimeUnit.HOURS.toMillis(48));
You can compare that with any Date object to see which occurred earlier in time - again, with no reference to any particular time zone.
(This isn't an easily testable solution, admittedly - I prefer to abstract System.currentTimeMillis() behind a Clock interface, so that I can test with a fake clock set to whatever time I want.)
Unless you need a string representation, ignore it - as soon as you want a string representation, you need to think about both which calendar system and time zone you're interested in.
Note that you talk about "today's date" in the question - if you mean the start of a particular day, then the time zone is relevant, and you'll need to do more work.
Finally, I'd suggest that if you possibly can, you use either java.time.* from Java 8, or Joda Time instead of java.util.Date etc. The first two are both much better APIs than the last.
The below code always prints the today's date object in local time zone.
Yes, that's because Date.toString() uses the local time zone. That's just what it (unfortunately) does, and it doesn't mean that the Date object is "in" the local time zone.
See the correct answer by Jon Skeet for details.
Yesterday and Day Before
Your requirement is unclear, but it seems you want to test if the target date-time string represents a date-time that lies within the 48-hour period before the beginning of today as defined by UTC time zone. In other words, yesterday or day before.
Avoid java.util.Date
Avoid using the java.util.Date and .Calendar classes bundled with Java. They are notoriously troublesome. Instead use either Joda-Time or the new java.time in Java 8 (inspired by Joda-Time). Both libraries have a date-time class that knows its own assigned time zone, unlike java.util.Date.
Half-Open Span Of Time
And both libraries have classes to represent a span of time. Comparisons are done by the "Half-Open" approach where the beginning is inclusive and the ending exclusive. So your two-day period is defined as the first moment of day-before-yesterday (inclusive) and running up to, but not including, the first moment of today (exclusive).
ISO 8601
Your string format is defined by the ISO 8601 standard. Both Joda-Time and java.time use ISO 8601 for defaults in parsing and generating strings. So they have a built-in formatter to parse your string. Merely pass the string.
Immutable Objects
Joda-Time uses immutable objects. Rather than modify ("mutate") an existing object, a new object is instantiated with values based on the original. The reason is for thread-safety.
Joda-Time
Here is some example code in Joda-Time 2.4.
DateTime target = new DateTime( "2014-01-02T03:04:05.789Z", DateTimeZone.UTC );
DateTime nowUtc = DateTime.now( DateTimeZone.UTC );
DateTime today = nowUtc.withTimeAtStartOfDay();
DateTime dayBeforeYesterday = today.minusDays( 2 ).withTimeAtStartOfDay();
Interval interval = new Interval( dayBeforeYesterday, today ); // Half-Open.
boolean hit = interval.contains( target );

Date comparison confusion

I have due_date = 2014-05-09 11:36:41.816.
I want to check condition that if today date is same as due_date or 1 day less then due_date then user can renew other wise have to show message that too early to renew.
means if I renew on date 8 then user can do but if user do it on date 7 then he is not allowed and display message.
I know that to check for same day means date 9, i can use :
Timestamp t = new Timestamp(new Date().getTime());
if (t.compareTo(due_date)==0){
//renew book
}
but i don't know that how to do for 1 day before calculation.
So any guidance to do for that.
Decent Date-Time Library
You should be using either Joda-Time or the new java.time in Java 8, as the old java.util.Date and .Calendar classes are notoriously troublesome.
Time Zone
You should not ignore the issue of time zone. Omitting time zone means your JVM's (host computer's) default time zone will apply. Your results will vary.
The definition of a "day" and "yesterday" depends on your particular time zone.
Use a proper time zone name (mostly continent slash city). Avoid the 3 or 4 letter codes as they are neither standardized nor unique.
If your input string has no time zone offset, meaning it is in UTC, then specify using the built-in constant DateTimeZone.UTC.
Interval
Joda-Time offers the Interval class to define a span of time. In your case the span is two days, the due date's day plus the day before. (By the way, both your posted questions and your programming will improve if you work harder at focusing and simplifying your problem as I just did in that preceding sentence.)
Half-Open
Usually in date-time work we use the "half-open" approach to define a span. That means the beginning is inclusive and the ending in exclusive for purposes of comparison. So for your purpose we want to run from the first moment of the day before due date up to, but not including, the first moment of the day *after* due date.
ISO 8601
Your input string is nearly in ISO 8601 standard format. Just replace the SPACE with a T. Joda-Time has built-in parsers for ISO 8601 formats.
Example Code
Example code in Joda-Time 2.3.
String inputDueDateRaw = "2014-05-09 11:36:41.816"
String inputDueDate = inputDueDateRaw.replace( " ", "T" );
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" );
DateTime due = new DateTime( inputDueDate, timeZone ); // Note the time zone by which to interpret the parsing of the string.
DateTime dayBeforeDue = due.withTimeAtStartOfDay().minusDays( 1 ).withTimeAtStartOfDay();
DateTime dayAfterDue = due.withTimeAtStartOfDay().plusDays( 1 ).withTimeAtStartOfDay(); // Half-open. Up to but not including day after.
Interval renewalInterval = new Interval( dayBeforeDue, dayAfterDue );
Test if the current moment is within that interval, using half-open approach to comparison.
boolean isNowEligibleForRenewal = renewalInterval.contains( DateTime.now() );
The actual value a.compareTo(b) returns is meaningless. The only thing you can trust is that if it's positive a is "larger" than b, and if it's negative, a is "smaller". You can't count on its absolute value to determine the difference between the two.
You could, however, just compare the unix time representation of both dates:
TimeStamp due_date = ...;
long dueDateMillis = due_date.getTime();
long t = System.currTimeMillis();
long threshold = 24L * 60L * 60L * 1000L; // One day in milliseconds
if (dueDateMillis - t <= threshold) {
// Renew book
}
Another way to do this is using the Calendar object:
Calendar today = Calendar.getInstance();
today.setTimeInMillis(System.currentTimeMillis()); // time today
Timestamp dueDateTs = new Timestamp(...);
Calendar dueDate = Calendar.getInstance();
dueDate.setTimeInMillis(dueDateTs.getTime());
dueDate.roll(Calendar.DAY_OF_YEAR, false); // to subtract 1 day
if(today.after(dueDate)) {
// do your magic
}

Categories