Date comparison confusion - java

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
}

Related

Getting the startime and endtime of the day in epochmillis for different timezones - java

I am trying to get the start time (00:00:00) and the end time (23:59:59) of a day in the PST time zone. I have tried the following code, but for some reason, I am only getting the start and end times in UTC. I have tried changing the timezone to include "America/Los_angeles", but the output timestamp is always showing start and end times for GMT/UTC.
My code:
val time_zone = ZoneId.of("America/Los_Angeles")
val today_date = LocalDate.now(time_zone).plusDays(0)
val start_time = today_date + " " + "00:00:00"
val end_time = today_date + " " + "23:59:59"
val date_format = new SimpleDateFormat("yyyy-MM-dd");
val start_millis = date_format.parse(start_time).getTime();
val end_millis = date_format.parse(end_time).getTime();
start_millis
Output:
res375: Long = 1656460799000
In the epoch converter, 1656460799000 gives me this:
Anything I am missing here? Should I update any package, etc.?
java.time
The modern approach uses the java.time classes only.
No need to ever use SimpleDateFormat, Date, Calendar, and the other terrible legacy date-time classes. If need be, you can convert to and fro via new conversion methods added to the old classes.
Start of day
I am trying to get the start time (00:00:00)
Do not assume the day starts at 00:00. Some dates in some zones start at another time such as 01:00. Let java.time determine the first moment of the day using LocalDate#atStartOfDay.
End of day
the end time (23:59:59) of a day
You would be missing an entire last second of the day with that approach.
Date-time work is commonly done with the Half-Open approach. In Half-Open, the beginning is inclusive while the ending is exclusive. So a day starts with the first moment of the day, and runs up to, but does not include, the first moment of the following day. Half-Open approach neatly contains that full last second of the day.
Time zones
PST time zone.
There is no such thing as a time zone named PST. Such 2-4 letter pseudo-zones are used by the popular media to indicate a hint about the time zone. But these pseudo-zones are not standardized, and are not even unique! Use only for localized presentation to humans, never for data storage or data exchange.
Real time zones are named with Continent/Region.
Perhaps by “PST” you meant “Pacific Standard Time”, which often indicates America/Tijuana, or America/Los_Angeles or America/Vancouver or others.
Or perhaps by “PST” you meant “Philippines Standard Time” covering the Asia/Manila time zone.
Example code
Capture the current moment as seen in a time zone.
ZoneId z = ZoneId.of( "America/Los_Angeles" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
Extract the date.
LocalDate today = zdt.toLocalDate() ;
Determine the first moment of the day.
ZonedDateTime zdtStartOfDay = today.atStartOfDay( z ) ;
And determine the first moment of the following day.
ZonedDateTime zdtStartOfFollowingDay = today.plusDays( 1 ).atStartOfDay( z ) ;
You may want to see the length of time. Not all days are 24 hours.
Duration d = Duration.between( zdtStartOfDay , zdtStartOfFollowingDay ) ;
Adjust both moments to UTC by extracting an Instant object. That class represents a moment as seen in UTC.
Instant start = zdtStartOfDay.toInstant() ;
Instant end = zdtStartOfFollowingDay.toInstant() ;
For each, get the count of milliseconds since the epoch reference of first moment of 1970 as seen in UTC, 1970-01-01T00:00Z.
long startMilli = start.toEpochMilli() ;
long endMilli = end.toEpochMilli() ;
However, I strongly recommend against tracking time as a count of milliseconds. This approach is confusing, as at least a couple dozen epoch reference points are commonly used. And a long cannot be interpreted by a human reader, so mistakes may go unnoticed.
Instead, data storage and data exchange should generally be done as text using the standard ISO 8601 formats. The java.time classes use these standard formats by default when parsing/generating text.
String startText = start.toString() ;
String endText = end.toString() ;
ThreeTen-Extra
You may want to add the ThreeTen-Extra library to your project. This gives you access to the Interval class, to represent a span of time as a pair of Instant objects.
Interval allDayLongToday = org.threeten.extra.Interval.of( start , end ) ;
This class provides several helpful methods. These include contains, encloses, abuts, union, intersection, and more.
Instant invoiceRecorded = … some `Instant` ;
boolean invoiceRecordedToday = allDayLongToday.contains( invoiceRecorded ) ;
Just add this section to your code:
date_format.setTimeZone(TimeZone.getTimeZone("PST"));
Then it will work as you want :)

Comparing dates in MMYY format

So I am making a Java program that processes a user's fake credit card and I am trying to make an expiration verification conditional statement. However, when I run my program, I get a "String cannot be converted to int" error. I would like to know how should I use the current month and year to check if the date entered by the user has actually expired.
do {
System.out.print("Enter the expiration date mmyy: ");
expiration = expnum.nextInt();
DateFormat dateformat = new SimpleDateFormat("MMyy");
Date date = new Date();
System.out.println(dateformat.format(date));
int currentdate = dateformat.format(date);
if (currentdate <= expiration) {
check = check + 1;
} else {
check = 1;
}
} while (check == 1);
While #ManoDestra's solution will work, I would prefer to keep the types/data sensible. Thus, rather than convert the existing date into a int (which is kind of nonsensical, and the format followed by parse feels nasty), I would prefer to parse the expiration into a date and then compare directly. Something like this:
expiration = expnum.nextInt();
DateFormat dateformat = new SimpleDateFormat("MMyy");
Date expiryDate = dateFormat.parse(expiration);
Date currentDate = new Date();
if (currentDate.isAfter(expiryDate)) {
// card has expired
} else {
// card is still active
}
You'll probably need to tweak this depending on when you think the expiry actually happens. If the expiry is specified as "0816" is that 01-Aug-2016 00:00:00.000, or 31-Aug-2016 23:59:59.999, or some point in between?
It's a call you have to make (probably by looking at the credit card spec), but that's another thing this approach has compared to the int-converting one: it's not just an abstract sense of "using proper types", but it translates to the real world too. By converting the expiration string to a Date, you need to think about exactly what instant in time that represents, and exactly which values of "now" should count as expired and which should not.
YearMonth class
The YearMonth class represents, well, a year and a month.
java.time
This class is part of the java.time framework built into Java 8 and later. These classes supplant the old troublesome date-time classes such as java.util.Date. See Oracle Tutorial. Much of the functionality has been back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP.
Parsing a String
Use a DateTimeFormatter to parse your input string. When the century is omitted the 21st century 20 is assumed.
String input = "0616";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern ( "MMyy" );
YearMonth expiration = YearMonth.parse ( input , formatter );
Dump to console.
System.out.println ( "yearMonth = " + yearMonth );
yearMonth = 2016-06
Time Zone
Compare to the current YearMonth. Determining the current year-month means getting the current date. And determining the current date requires a time zone. The Question and other Answers ignore this crucial issue. For any given moment the date varies around the globe by time zone. A few minutes after Paris is a new day while still “yesterday” in Montréal.
If omitted as an optional argument, the JVM’s current default time zone is silently implicitly applied. The current default can change at any time, even during runtime(!). Better to specify the expected/desired time zone.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
YearMonth currentYearMonth = YearMonth.now( zoneId );
If your business rules happen to use UTC as the time zone, pass the handy constant ZoneOffset.UTC as the time zone argument.
Compare
Lastly, we compare using isBefore, isAfter, or equals.
Boolean expired = currentYearMonth.isAfter( expiration );
Rather than passing around strings or integers for the year and month, pass around these YearMonth objects. You get the benefits of type safety, guaranteed valid values, and more self-documenting code.
Compare it as a String in the form yyMM, whose natural ordering is correct:
int expiration; // MMyy
String expirationStr = String.format("%02d%02d", expiration % 100, expiration / 100);
String now = new SimpleDateFormat("yyMM").format(new Date());
if (expirationStr.compareTo(now) < 0)
// expired
It's not an int. It's a string. This is wrong:
int currentdate = dateformat.format(date);
If you really WANT an int, then convert it to an int:
int currentdate = Integer.parseInt(dateformat.format(date));
However, it won't be a terribly sensible int. If you wish to make this a more sensible int for comparison, then you'd have to put the year first, THEN the month (format: yyMM, or yyyyMM). That way, it will be a consecutive numerical comparison that CAN be compared against other credit card dates. Or, you could simply convert it to a Date or Calendar instead and use date comparisons.
Also, you should make the variable, check, a Boolean value. You have no need for it to be an numeric value.
You can replace expnum.nextInt(); with Integer.parseInt(expnum.nextLine()); This will take the input string, and convert it to an int. If they don't put an int though, it will through an exception, so you can put that inside a try-catch statement (and put that in like in a while loop or something so it keeps asking till they answer in the proper format if you want).

How to retrieve minutes from string date?

I have stored date in a string. Now I want to get minutes from the date string. How can I convert it into minutes?
Here is how I stored in a class:
public String fromDate;
public String toDate;
I have set getter and setter methods. I have saved the date value now I want to retrive the value and convert to minutes.
Retriving Like this:
Calendar c = Calendar.getInstance();
String datefrom = eventData.getFromDate();
I tried using this calendar instance:
c.set(Calendar.HOUR, hour);
c.set(Calendar.MINUTE, minute);
c.set(Calendar.DATE,day);
Date datefrom = c.getTime();
startTime = String.valueOf(datefrom);
int hour = c.get(Calendar.HOUR);
int totalMinutes = hour * 60;
But this I can get from Date object. I have stored date in String format. How can I convert this?
Use Joda-Time:
String fromDate;
String toDate;
DateTimeFormatter format = new DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
DateTime fromDT = format.parseDateTime(fromDate);
DateTime toDT = format.parseDateTime(toDate);
Duration duration = new Duration(fromDT, toDT);
int minutes = duration.getStandardMinutes();
To import in Android Studio, update your build.gradle file:
apply plugin: 'android'
dependencies {
compile 'joda-time:joda-time:2.4'
compile 'joda-time:joda-time:2.2'
}
To convert a String to Date in Java you would have to use the DateFormat like the sample below:
String string = "January 26, 2016";
DateFormat format = new SimpleDateFormat("MMMM d, yyyy", Locale.ENGLISH);
Date date = format.parse(string);
System.out.println(date); // Tue Jan 26 00:00:00 GMT 2016
then you can go ahead with your Calendar implementation.
Usually i'd suggest to parse the time with a SimpleDateFormat, but I think in this case (since the dates seem to have a defined form and there might be problems with the timezones) i'll suggest to retrieve the information yourself:
String date = "Wed Jan 27 07:25:29 GMT+05:30 2016";
String[] times = date.substring(11, 16).split(":");
int minutes = Integer.parseInt(times[0]) * 60 + Integer.parseInt(times[1]);
System.out.println(minutes);
The part date.substring(11, 16) extracts the hours and minutes part from the string ("07:25").
The part .split(":"); splits the string "07:25" into two strings: "07" and "25".
after that you just parse those numbers to integers with Integer.parseInt(...) and calculate the number of minutes!
To get the minutes from a String is possible to use a DateFormat to convert the string to a Date and after use your code.
Your Question is really two questions:
How to parse a String to get a date-time object
How to get number of minutes since start-of-day from a date-time object
The first one, parsing a String into a date-time, has been covered at least 1,845 times on Stack Overflow, so I will skip it. The second Question is addressed below.
Please try to make your questions more clear. And focus on a single topic as narrowly as possible, as that is the intention for Stack Overflow.
Minutes-Of-Day
What you seem to want is called “Minutes-Of-Day”, the number of minutes since the start of the day.
Be careful and thoughtful here as there are two different definitions for minutes-of-day. You can get the actual number of minutes for a specific day in a specific time zone. Or you can calculate for a generic 24-hour day. Because of Daylight Saving Time (DST) and other anomalies, a day is not necessarily 24 hours long. For example, in most of the United States the use of DST means a day may be 23, 24, or 25 hours long.
The Question’s code and other Answers ignore the crucial issue of time zone (a common mistake in date-time work). If you do not specify a time zone, your JVM’s current default time zone is silently applied. Not good… that default can change at any moment, even during runtime! Better to always specify the time zone you expect/desire.
Avoid Old Date-Time Classes
The old date-time classes bundled with the earliest versions of Java are notoriously troublesome. Avoid them. Instead use the java.time framework built into Java 8 and later (see Tutorial). If that technology is not available to you, use the Joda-Time library (which inspired java.time). Examples below are in java.time in Java 8 Update 66.
java.time
Let’s look at March 3rd, 2015. This day was the "Spring ahead" DST changeover day for most of the United States. The clock jumped from 2 AM to 3 AM. So 03:00:00.0 on this day meant two hours (120 minutes) actually elapsed since the start of the day. If we treat this as a generic 24-hour day, we would say three hours (180 minutes) elapsed. The java.time classes can calculate minutes-of-day in both definitions.
First we get 3 AM on that changeover day. We use one of the time zones which recognized DST.
ZoneId zoneId = ZoneId.of ( "America/Los_Angeles" );
ZonedDateTime zdt = ZonedDateTime.of ( 2015 , 3 , 8 , 3 , 0 , 0 , 0 , zoneId );
Generic 24-Hour Day
Next we get the minutes since start of day assuming a generic 24-hour day. The ChronoField enum provides many ways to access TemporalField values such as MINUTE_OF_DAY.
long minutesOfDayForGeneric24HourDay = zdt.get ( ChronoField.MINUTE_OF_DAY );
Actual Day
To get the actual number of minutes elapsed since the start of this particular day for this particular time zone in which DST was changing over, we must do a bit more work. We have to determine the first moment of the day from which we can calculate elapsed time. To get that first moment, we must go through the LocalDate class which is a date-only value without time-of-day nor time zone. On that LocalDate object we call atStartOfDay to adjust back into a date-time value (a ZonedDateTime). You might think you could skip this by assuming the day starts at 00:00:00.0 but that is not always true.
ZonedDateTime zdtStart = zdt.toLocalDate ().atStartOfDay ( zoneId );
Now calculate elapsed time. The Duration class represents a span of time as hours, minutes, and seconds. From that Duration we can ask the total number of minutes, converting hours to minutes.
Duration duration = Duration.between ( zdtStart , zdt );
long minutesOfDayForActualDay = duration.toMinutes ();
Dump to console. Note how the generic ChronoField approach says 180 minutes while the actual Duration approach yields 120 minutes.
System.out.println ( "zdt: " + zdt + " | minutesOfDayForGeneric24HourDay: " + minutesOfDayForGeneric24HourDay + " | duration: " + duration + " | minutesOfDayForActualDay: " + minutesOfDayForActualDay );
zdt: 2015-03-08T03:00-07:00[America/Los_Angeles] | minutesOfDayForGeneric24HourDay: 180 | duration: PT2H | minutesOfDayForActualDay: 120

Printing Time and Date in both Universal Time and Standard Time

Writing a Java application that takes user input into a Time and Date class, but I am not sure how to take this user input and convert it into Universal and Standard time... I have spent multiple hours surfing the web and stack overflow and have not been able to find a solution.
I have hours, minutes, seconds, year, month, day all in separate integer variables and need to display them in Universal and Standard time.
Thanks for taking a look...
There are two solutions:
first is place all of input in the string and parse it:
String dateStr = ""
//put your input in this string in some format/ example:
//dateSttr = year + "." + month + "." + day + " " + hour + ":" + minute;
//It is better to use StringBuilder
DateFormat inputFormat = new SimpleDateFormat("yyyy.MM.dd hh:mm");
//note that hh is 12h-format and HH is 24h-format
DateFormat outputFormat1 = new SimpleDateFormat("your_outputFormat");
DateFormat outputFormat2 = new SimpleDateFormat("your_another_outputFormat");
Date date = inputFormat.parse(dateStr);
String o1, o2;
o1 = outputFormat1.format(date);
o2 = outputFormat2.format(date);
//o1 and o2 is your result.
For the rules, how this formats is done, see javadoc
The second solution is to get a new date and set your parameters:
Calendar cln = Calendar.getInstance().clear();
//by default you get a calendar with current system time
//now set the fields. for example, day:
cln.set(Calendar.YEAR, 2015);
cln.set(Calendar.MONTH, Calendar.FEBRUARY);
cln.set(Calendar.DAY_OF_MONTH, 17);
cln.set(Calendar.HOUR_OF_DAY, 18);//Calendar.HOUR for 12h-format
cln.set(Calendar.MINUTE, 27);
See more about setting calendar in javadoc
Note, that in the second variant, you might have some fields undefiend.
If #JonSkeet 's assumption and mine is correct, you're starting with either UTC or your local time. Displaying it is just a matter of formatting your output.
For the other type of time, you add or subtract a number of hours, which you can find on the web. The tricky part is that this may push you into the next calendar day, or pull you back into the previous one. To deal with that, I figure you want to either
implement an adder for year, month, day, hour--or
convert those to decimal somethings (Excel uses days, for instance, where as I write this it's 42328.08813), shift the value by the appropriate number of hours, and convert it back.
java.time
The Answer by TEXHIK is correct, but outdated. Also, as others mentioned, I do not know what you mean by "Universal and Standard time". But I'll try to get you part way there.
As of Java 8, the old java.util.Date/.Calendar classes have been supplanted by the new java.time framework. The new classes are inspired by the highly successful Joda-Time framework, intended as its successor, similar in concept but re-architected. Defined by JSR 310. Extended by the ThreeTen-Extra project. See the Tutorial.
The ZonedDateTime class has a factory method taking numbers for year, month, and so on.
Plus you must specify a time zone. If your numbers represent a date-time in UTC, use the ZoneOffset.UTC constant. For other time zones, specify a ZoneId object by using a proper time zone name; never use the 3-4 letter codes such as EST or IST as their are neither standardized nor unique.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
// ZoneId zoneId = ZoneOffset.UTC; // ZoneOffset is a subclass of ZoneId.
ZonedDateTime zdt = ZonedDateTime.of( 2015 , 1 , 2 , 3 , 4 , 5 , 6 , zoneId );
zdt: 2015-01-02T03:04:05.000000006-05:00[America/Montreal]
You can convert to UTC or another time zone.
ZonedDateTime zdt_Kolkata = zdt.withZoneSameInstant ( ZoneId.of("Asia/Kolkata") );
ZonedDateTime zdt_Utc = zdt.withZoneSameInstant ( ZoneOffset.UTC );
zdt_Kolkata: 2015-01-02T13:34:05.000000006+05:30[Asia/Kolkata]
zdt_Utc: 2015-01-02T08:04:05.000000006Z
If working with classes not yet updated for java.time, convert to a java.util.Date. First extract a Instant object, a moment on the timeline always in UTC.
java.util.Date date = java.util.Date.from ( zdt.toInstant () );

Convert UTC date into milliseconds

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();

Categories