Related
I need to extract the date field from DB and store it in a VO. How can I compare the hours difference from two dates.
For ex:
Let's say date1 = 01-SEP-17 10:00:00 and date2 = 05-SEP-17 12:00:00. I need to compare the two dates and perform some operations like:
if(hours>10){
//do something
}
if(hours<10){
//do something else
}
I'm just able to calculate the difference between the hours (date2-date1) as 2 but how to consider the date too while calculating the difference between the hours?
My present code:
Date dateA = someVO.getDate();
long date = System.currentTimeMillis();
SimpleDateFormat df = new SimpleDateFormat("dd-MM-YY HH:mm:ss");
Date date1 = new Date(date);
Date date2 = df.parse(dateA.toString());
long date1Hours = date1.getHours();
long date2Hours = date2.getHours();
long dateDiff = date1Hours-date2Hours;
if(dateDiff>10){
//something
}
else if(dateDiff<10){
//something else
}
Easy enough to do using the new Java-Time API added in Java 8:
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern("dd-MMM-yy HH:mm:ss")
.toFormatter(Locale.US);
LocalDateTime date1 = LocalDateTime.parse("01-SEP-17 10:00:00", fmt);
LocalDateTime date2 = LocalDateTime.parse("05-SEP-17 12:00:00", fmt);
long hours = ChronoUnit.HOURS.between(date1, date2);
System.out.println(hours);
Output
98
First you need to change the pattern used in SimpleDateFormat, and also use a java.util.Locale to specify that the month name is in English (otherwise it uses the system default locale, and it's not guaranteed to always be English).
Then you get the correspondent millis value of each Date, calculate the difference between them and convert this to hours, using a java.util.concurrent.TimeUnit:
SimpleDateFormat df = new SimpleDateFormat("dd-MMM-yy HH:mm:ss", Locale.ENGLISH);
Date date1 = df.parse("01-SEP-17 10:00:00");
Date date2 = df.parse("05-SEP-17 12:00:00");
// get the difference in hours
long dateDiff = TimeUnit.MILLISECONDS.toHours(date2.getTime() - date1.getTime());
dateDiff will be 98.
If you want to compare with the current date, just use new Date().
Daylight Saving Time issues
There's one problem with this approach. Although it doesn't make a difference for most part of the year, there can be differences due to Daylight Saving Time changes.
By default, SimpleDateFormat uses the JVM default timezone. If between the 2 dates there's a Daylight Saving Time changeover (or just an offset change), the result might be different.
Example: in Africa/Windhoek timezone, in September 3rd 2017, at 2 AM, clocks shifted 1 hour forward, from 2 AM to 3 AM (and the offset changed from +01:00 to +02:00). This means that, at that day, all local times between 2 AM and 2:59 AM don't exist in this timezone (it's like they "skipped" this hour).
So, if the JVM default timezone is Africa/Windhoek, then the difference using the code above will be 97 hours (and not 98).
Even if your JVM default timezone is not Africa/Windhoek, this can still happen, depending on the timezone and the dates involved.
Not only that, but the default timezone can be changed without notice, even at runtime. It's always better to specify which timezone you're working with instead of just relying on the default.
You can't avoid DST effects (unless you use UTC), but at least you can choose which timezone you're going to use instead of relying on the system default (that can be changed without notice).
It's possible to set a timezone in the formatter, so all dates will be parsed taking this timezone into account. In the example below, I'm using Europe/London, but of course you can change to one that best suits your case:
// set Europe/London timezone in the SimpleDateFormat
df.setTimeZone(TimeZone.getTimeZone("Europe/London"));
Now all the parsed dates will be considered to be in London timezone (but remind that DST effects will still be considered - the advantage is that you know what timezone you're using and any changes in the JVM's default won't make your code suddenly start giving different and unexpected results).
Always use IANA timezones names (always in the format Continent/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 all timezones using TimeZone.getAvailableIDs() - then you can choose the one that best suits your case.
If you don't want to consider DST effects, you can use TimeZone.getTimeZone("UTC") - because UTC is a standard without DST changes.
Java new Date/Time API
The old classes (Date, Calendar and SimpleDateFormat) have lots of problems and design issues, and they're being replaced by the new APIs.
If you're using Java 8, consider using the new java.time API. It's easier, less bugged and less error-prone than the old APIs.
If you're using Java <= 7, you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, there's the ThreeTenABP (more on how to use it here).
The code below works for both.
The only difference is the package names (in Java 8 is java.time and in ThreeTen Backport (or Android's ThreeTenABP) is org.threeten.bp), but the classes and methods names are the same.
First you need to parse the inputs (using a DateTimeFormatter) and specify in what timezone they are. As the dates also have a timezone, I'm using a ZonedDateTime, which is the best choice for this case.
Then you can easily calculate the difference in hours using a ChronoUnit. In the example below, I'm also using London timezone as an example:
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
// case insensitive for month name in all caps
.parseCaseInsensitive()
// date/time pattern
.appendPattern("dd-MMM-yy HH:mm:ss")
// use English locale for month name
.toFormatter(Locale.ENGLISH)
// set a timezone
.withZone(ZoneId.of("Europe/London"));
// parse the dates
ZonedDateTime z1 = ZonedDateTime.parse("01-SEP-17 10:00:00", fmt);
ZonedDateTime z2 = ZonedDateTime.parse("05-SEP-17 12:00:00", fmt);
// calculate the difference in hours
long diffHours = ChronoUnit.HOURS.between(z1, z2);
If you want to use UTC, just change the ZoneId to ZoneOffset.UTC constant. If you want to compare with the current date, just use:
// use the same ZoneId used in the formatter if you want to consider DST effects
ZonedDateTime.now(ZoneId.of("Europe/London"));
Conversions to/from Date
If you still need to work with java.util.Date, it's possible to convert from/to the new API. In Java 8 you can use native methods, and in Java <=7 the ThreeTen Backport has the org.threeten.bp.DateTimeUtils class.
To convert a Date to the new classes:
Date date = // java.util.Date
// convert to zoneddatetime (java 8)
ZonedDateTime z = date.toInstant().atZone(ZoneId.of("Europe/London"));
// convert to zoneddatetime (java 7 ThreeTen Backport)
ZonedDateTime z = DateTimeUtils.toInstant(date).atZone(ZoneId.of("Europe/London"));
To convert a ZonedDateTime back to a date:
// convert to zoneddatetime (java 8)
Date date = Date.from(z.toInstant());
// convert to zoneddatetime (java 7 ThreeTen Backport)
Date date = DateTimeUtils.toDate(z.toInstant());
You've essentially already got the times in milliseconds. You could always just compare the milliseconds directly instead.
long tenHoursInMillis = 36000000;
long dateVOMillis = someVO.getDate().getTime();
long dateSysMillis = System.currentTimeMillis();
if(dateSysMillis - dateAMillis > tenHoursInMillis) {
// do something
}
else if(dateSysMillis - dateAMillis < tenHoursInMillis) {
// do something else
}
// do something when they're equal
How to calculate the difference between current day and date of the object that user had previously selected from jXDatePicker swing component and that had been added as Date to that object.
In my current code at the last line I'm getting this error message:
no suitable method found for between(Date, Date)
Date currentDate = new Date();
Date objDate = obj.getSelectedDate(); //getting date the user had
//previously selected and that been
//added to object
long daysDifference = ChronoUnit.DAYS.between(objDate, currentDate);
You are mixing up the legacy Date-Time code with the new Java 8 Date-Time API. The ChronoUnit.between(Temporal, Temporal) method is from java.time.temporal package which takes two Temporal objects. It does not support the java.util.Date as an argument, hence the compilation error.
Instead of using the legacy Date class, you can use java.time.LocalDate class , and then get the difference between the two dates.
LocalDate currentDate = LocalDate.now(ZoneId.systemDefault());
LocalDate objDate = obj.getSelectedDate(); // object should also store date as LocalDate
long daysDifference = ChronoUnit.DAYS.between(objDate, currentDate);
Update
As per your comment , the objDate can only be a Date, so in this case you can use the inter-operability between the Legacy Date -Time and the Java 8 Date-Time classes.
LocalDateTime currentDate = LocalDateTime.now(ZoneId.systemDefault());
Instant objIns = obj.getSelectedDate().toInstant();
LocalDateTime objDtTm = LocalDateTime.ofInstant(objIns, ZoneId.systemDefault());
long daysDifference = ChronoUnit.DAYS.between(objDtTm, currentDate);
Update 2
As pointed out by Ole V.V in the comments, to handle Time Zone issues that may occur , calculating the difference using Instant is a better approach.
Instant now = Instant.now();
long daysDifference = obj.getSelectedDate()
.toInstant()
.until(now, ChronoUnit.DAYS);
I agree with Pallavi Sonal’s answer that when you can use the modern java.time classes, you should keep your use of the oldfashioned classes like Date to an absolute minimum. I don’t know JXDatePicker, but I see that its getDate method returns a Date. So the first thing you should do with this is convert it to a more modern thing.
It may seem from your question that in this case you are only concerned with days, not times. If this is correct, Pallavi Sonal is also correct that LocalDate is the correct class for you. I think that this conversion should work for you
LocalDate selectedDate = jXDatePicker.getDate()
.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDate();
This is with a bit of reservation for time zone issues since I don’t know in which time zone the date picker is giving you the date. Once you know that, you can fill in the correct time zone instead of ZoneId.systemDefault().
Unfortunately I am not aware of a date picker component that can give you a LocalDate directly. There could well be one, I hope there is, so it’s probably worth searching for one.
I have a timestamp that's in UTC and I want to convert it to local time without using an API call like TimeZone.getTimeZone("PST"). How exactly are you supposed to do this? I've been using the following code without much success:
private static final SimpleDateFormat mSegmentStartTimeFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
Calendar calendar = Calendar.getInstance();
try {
calendar.setTime(mSegmentStartTimeFormatter.parse(startTime));
}
catch (ParseException e) {
e.printStackTrace();
}
return calendar.getTimeInMillis();
Sample input value: [2012-08-15T22:56:02.038Z]
should return the equivalent of [2012-08-15T15:56:02.038Z]
Date has no timezone and internally stores in UTC. Only when a date is formatted is the timezone correction applies. When using a DateFormat, it defaults to the timezone of the JVM it's running in. Use setTimeZone to change it as necessary.
DateFormat utcFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
utcFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = utcFormat.parse("2012-08-15T22:56:02.038Z");
DateFormat pstFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
pstFormat.setTimeZone(TimeZone.getTimeZone("PST"));
System.out.println(pstFormat.format(date));
This prints 2012-08-15T15:56:02.038
Note that I left out the 'Z' in the PST format as it indicates UTC. If you just went with Z then the output would be 2012-08-15T15:56:02.038-0700
Use the modern Java date & time API, and this is straightforward:
String inputValue = "2012-08-15T22:56:02.038Z";
Instant timestamp = Instant.parse(inputValue);
ZonedDateTime losAngelesTime = timestamp.atZone(ZoneId.of("America/Los_Angeles"));
System.out.println(losAngelesTime);
This prints
2012-08-15T15:56:02.038-07:00[America/Los_Angeles]
Points to note:
There’s a little bug in your expectations. The Z in your timestamp means UTC, also known as Zulu time. So in your local time value, the Z should not be there. Rather you would want a return value like for example 2012-08-15T15:56:02.038-07:00, since the offset is now -7 hours rather than Z.
Avoid the three letter time zone abbreviations. They are not standardized and therefore most often ambiguous. PST, for example, may mean Philppine Standard Time, Pacific Standard Time or Pitcairn Standard Time (though S in an abbreviation is often for summer time (meaning DST)). If you intended Pacific Standard Time, that isn’t even a time zone, since in summer (where your sample timestamp falls) Pacific Daylight Time is used instead. Instead of the abbreviations use time zone IDs in the format region/city as in my code.
Timestamps are generally best handled as Instant objects. Convert to ZonedDateTime only when you have a need, like for presentation.
Question: Can I use the modern API with my Java version?
If using at least Java 6, you can.
In Java 8 and later the new API comes built-in.
In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (that’s ThreeTen for JSR-310, where the modern API was first defined).
On Android, use the Android edition of ThreeTen Backport. It’s called ThreeTenABP, and I think that there’s a wonderful explanation in this question: How to use ThreeTenABP in Android Project.
Here is a Simple Modified solution
public String convertToCurrentTimeZone(String Date) {
String converted_date = "";
try {
DateFormat utcFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
utcFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = utcFormat.parse(Date);
DateFormat currentTFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
currentTFormat.setTimeZone(TimeZone.getTimeZone(getCurrentTimeZone()));
converted_date = currentTFormat.format(date);
}catch (Exception e){ e.printStackTrace();}
return converted_date;
}
//get the current time zone
public String getCurrentTimeZone(){
TimeZone tz = Calendar.getInstance().getTimeZone();
System.out.println(tz.getDisplayName());
return tz.getID();
}
Continuing from Stack Overflow question Java program to get the current date without timestamp:
What is the most efficient way to get a Date object without the time? Is there any other way than these two?
// Method 1
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date dateWithoutTime = sdf.parse(sdf.format(new Date()));
// Method 2
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
dateWithoutTime = cal.getTime();
Update:
I knew about Joda-Time; I am just trying to avoid additional library for such a simple (I think) task. But based on the answers so far Joda-Time seems extremely popular, so I might consider it.
By efficient, I mean I want to avoid temporary object String creation as used by method 1, meanwhile method 2 seems like a hack instead of a solution.
Do you absolutely have to use java.util.Date? I would thoroughly recommend that you use Joda Time or the java.time package from Java 8 instead. In particular, while Date and Calendar always represent a particular instant in time, with no such concept as "just a date", Joda Time does have a type representing this (LocalDate). Your code will be much clearer if you're able to use types which represent what you're actually trying to do.
There are many, many other reasons to use Joda Time or java.time instead of the built-in java.util types - they're generally far better APIs. You can always convert to/from a java.util.Date at the boundaries of your own code if you need to, e.g. for database interaction.
Here is what I used to get today's date with time set to 00:00:00:
DateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
Date today = new Date();
Date todayWithZeroTime = formatter.parse(formatter.format(today));
You can use the DateUtils.truncate from Apache Commons library.
Example:
DateUtils.truncate(new Date(), java.util.Calendar.DAY_OF_MONTH)
tl;dr
Is there any other way than these two?
Yes, there is: LocalDate.now
LocalDate.now(
ZoneId.of( "Pacific/Auckland" )
)
java.time
Java 8 and later comes with the new java.time package built-in. See Tutorial. Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP.
Similar to Joda-Time, java.time offers a LocalDate class to represent a date-only value without time-of-day and without time zone.
Note that time zone is critical to determining a particular date. At the stroke of midnight in Paris, for example, the date is still “yesterday” in Montréal.
LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) ) ;
By default, java.time uses the ISO 8601 standard in generating a string representation of a date or date-time value. (Another similarity with Joda-Time.) So simply call toString() to generate text like 2015-05-21.
String output = today.toString() ;
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, Java 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 Java SE 7
Much 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, 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.
The most straightforward way:
long millisInDay = 60 * 60 * 24 * 1000;
long currentTime = new Date().getTime();
long dateOnly = (currentTime / millisInDay) * millisInDay;
Date clearDate = new Date(dateOnly);
The standard answer to these questions is to use Joda Time. The API is better and if you're using the formatters and parsers you can avoid the non-intuitive lack of thread safety of SimpleDateFormat.
Using Joda means you can simply do:
LocalDate d = new LocalDate();
Update:: Using java 8 this can be acheived using
LocalDate date = LocalDate.now();
This is a simple way of doing it:
Calendar cal = Calendar.getInstance();
SimpleDateFormat dateOnly = new SimpleDateFormat("MM/dd/yyyy");
System.out.println(dateOnly.format(cal.getTime()));
It does not make sense to talk about a date without a timestamp with regards to the Date routines in the standard java runtime, as it essentially maps down to a specific millisecond and not a date. Said millisecond intrinsically has a time of day attached to it which makes it vulnerable to timezone problems like Daylight Savings Time and other calendar adjustments. See Why is subtracting these two times (in 1927) giving a strange result? for an interesting example.
If you want to work with dates instead of milliseconds, you need to use something else. For Java 8 there is a new set of methods providing exactly what you ask for. For Java 7 and earlier use http://www.joda.org/joda-time/
// 09/28/2015
System.out.println(new SimpleDateFormat("MM/dd/yyyy").format(Calendar.getInstance().getTime()));
// Mon Sep 28
System.out.println( new Date().toString().substring(0, 10) );
// 2015-09-28
System.out.println(new java.sql.Date(System.currentTimeMillis()));
// 2015-09-28
// java 8
System.out.println( LocalDate.now(ZoneId.of("Europe/Paris")) ); // rest zones id in ZoneId class
Definitely not the most correct way, but if you just need a quick solution to get the date without the time and you do not wish to use a third party library this should do
Date db = db.substring(0, 10) + db.substring(23,28);
I only needed the date for visual purposes and couldn't Joda so I substringed.
If all you want is to see the date like so "YYYY-MM-DD" without all the other clutter e.g. "Thu May 21 12:08:18 EDT 2015" then just use java.sql.Date. This example gets the current date:
new java.sql.Date(System.currentTimeMillis());
Also java.sql.Date is a subclass of java.util.Date.
Well, as far as I know there is no easier way to achieve this if you only use the standard JDK.
You can, of course, put that logic in method2 into a static function in a helper class, like done here in the toBeginningOfTheDay-method
Then you can shorten the second method to:
Calendar cal = Calendar.getInstance();
Calendars.toBeginningOfTheDay(cal);
dateWithoutTime = cal.getTime();
Or, if you really need the current day in this format so often, then you can just wrap it up in another static helper method, thereby making it a one-liner.
Use LocalDate.now() and convert into Date like below:
Date.from(LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant());
What about this?
public static Date formatStrictDate(int year, int month, int dayOfMonth) {
Calendar calendar = Calendar.getInstance();
calendar.set(year, month, dayOfMonth, 0, 0, 0);
calendar.set(Calendar.MILLISECOND, 0);
return calendar.getTime();
}
If you need the date part just for echoing purpose, then
Date d = new Date();
String dateWithoutTime = d.toString().substring(0, 10);
If you just need the current date, without time, another option is:
DateTime.now().withTimeAtStartOfDay()
Yo can use joda time.
private Date dateWitoutTime(Date date){
return new LocalDate(date).toDate()
}
and you call with:
Date date = new Date();
System.out.println("Without Time = " + dateWitoutTime(date) + "/n With time = " + date);
Check out Veyder-time. It is a simple and efficient alternative to both java.util and Joda-time. It has an intuitive API and classes that represent dates alone, without timestamps.
The most straigthforward way that makes full use of the huge TimeZone Database of Java and is correct:
long currentTime = new Date().getTime();
long dateOnly = currentTime + TimeZone.getDefault().getOffset(currentTime);
Here is a clean solution with no conversion to string and back, and also it doesn't re-calculate time several times as you reset each component of the time to zero. It also uses % (modulus) rather than divide followed by multiply to avoid the double operation.
It requires no third-party dependencies, and it RESPECTS THE TIMEZONE OF THE Calender object passed in. This function returns the moment in time at 12 AM in the timezone of the date (Calendar) you pass in.
public static Calendar date_only(Calendar datetime) {
final long LENGTH_OF_DAY = 24*60*60*1000;
long millis = datetime.getTimeInMillis();
long offset = datetime.getTimeZone().getOffset(millis);
millis = millis - ((millis + offset) % LENGTH_OF_DAY);
datetime.setTimeInMillis(millis);
return datetime;
}
Prefer not to use third-party libraries as much as possible. I know that this way is mentioned before, but here is a nice clean way:
/*
Return values:
-1: Date1 < Date2
0: Date1 == Date2
1: Date1 > Date2
-2: Error
*/
public int compareDates(Date date1, Date date2)
{
SimpleDateFormat sdf = new SimpleDateFormat("ddMMyyyy");
try
{
date1 = sdf.parse(sdf.format(date1));
date2 = sdf.parse(sdf.format(date2));
}
catch (ParseException e) {
e.printStackTrace();
return -2;
}
Calendar cal1 = new GregorianCalendar();
Calendar cal2 = new GregorianCalendar();
cal1.setTime(date1);
cal2.setTime(date2);
if(cal1.equals(cal2))
{
return 0;
}
else if(cal1.after(cal2))
{
return 1;
}
else if(cal1.before(cal2))
{
return -1;
}
return -2;
}
Well, not using GregorianCalendar is maybe an option!
I just made this for my app :
public static Date getDatePart(Date dateTime) {
TimeZone tz = TimeZone.getDefault();
long rawOffset=tz.getRawOffset();
long dst=(tz.inDaylightTime(dateTime)?tz.getDSTSavings():0);
long dt=dateTime.getTime()+rawOffset+dst; // add offseet and dst to dateTime
long modDt=dt % (60*60*24*1000) ;
return new Date( dt
- modDt // substract the rest of the division by a day in milliseconds
- rawOffset // substract the time offset (Paris = GMT +1h for example)
- dst // If dayLight, substract hours (Paris = +1h in dayLight)
);
}
Android API level 1, no external library.
It respects daylight and default timeZone. No String manipulation so I think this way is more CPU efficient than yours but I haven't made any tests.
We can use SimpleDateFormat to format the date as we like. here is a working example below:-
SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
System.out.println(dateFormat.format(new Date())); //data can be inserted in this format function
Output:
15/06/2021
Is there a simple or elegant way to grab only the time of day (hours/minutes/seconds/milliseconds) part of a Java Date (or Calendar, it really doesn't matter to me)? I'm looking for a nice way to separately consider the date (year/month/day) and the time-of-day parts, but as far as I can tell, I'm stuck with accessing each field separately.
I know I could write my own method to individually grab the fields I'm interested, but I'd be doing it as a static utility method, which is ugly. Also, I know that Date and Calendar objects have millisecond precision, but I don't see a way to access the milliseconds component in either case.
Edit: I wasn't clear about this: using one of the Date::getTime() or Calendar::getTimeInMillis is not terribly useful to me, since those return the number of milliseconds since the epoch (represented by that Date or Calendar), which does not actually separate the time of day from the rest of the information.
#Jherico's answer is the closest thing, I think, but definitely is something I'd still have to roll into a method I write myself. It's not exactly what I'm going for, since it still includes hours, minutes, and seconds in the returned millisecond value - though I could probably make it work for my purposes.
I still think of each component as separate, although of course, they're not. You can write a time as the number of milliseconds since an arbitrary reference date, or you could write the exact same time as year/month/day hours:minutes:seconds.milliseconds.
This is not for display purposes. I know how to use a DateFormat to make pretty date strings.
Edit 2: My original question arose from a small set of utility functions I found myself writing - for instance:
Checking whether two Dates represent a date-time on the same day;
Checking whether a date is within a range specified by two other dates, but sometimes checking inclusively, and sometimes not, depending on the time component.
Does Joda Time have this type of functionality?
Edit 3: #Jon's question regarding my second requirement, just to clarify: The second requirement is a result of using my Dates to sometimes represent entire days - where the time component doesn't matter at all - and sometimes represent a date-time (which is, IMO, the most accurate word for something that contains year/month/day and hours:minutes:seconds:...).
When a Date represents an entire day, its time parts are zero (e.g. the Date's "time component" is midnight) but the semantics dictate that the range check is done inclusively on the end date. Because I just leave this check up to Date::before and Date::after, I have to add 1 day to the end date - hence the special-casing for when the time-of-day component of a Date is zero.
Hope that didn't make things less clear.
Okay, I know this is a predictable answer, but... use Joda Time. That has separate representations for "a date", "an instant", "a time of day" etc. It's a richer API and a generally saner one than the built-in classes, IMO.
If this is the only bit of date/time manipulation you're interested in then it may be overkill... but if you're using the built-in date/time API for anything significant, I'd strongly recommend that you move away from it to Joda as soon as you possibly can.
As an aside, you should consider what time zone you're interested in. A Calendar has an associated time zone, but a Date doesn't (it just represents an instant in time, measured in milliseconds from the Unix epoch).
Extracting the time portion of the day should be a matter of getting the remainder number of milliseconds when you divide by the number of milliseconds per day.
long MILLIS_PER_DAY = 24 * 60 * 60 * 1000;
Date now = Calendar.getInstance().getTime();
long timePortion = now.getTime() % MILLIS_PER_DAY;
Alternatively, consider using joda-time, a more fully featured time library.
Using Calendar API -
Solution 1-
Calendar c = Calendar.getInstance();
String timeComp = c.get(Calendar.HOUR_OF_DAY)+":"+c.get(Calendar.MINUTE)+":"+c.get(Calendar.SECOND)+":"+c.get(Calendar.MILLISECOND);
System.out.println(timeComp);
output - 13:24:54:212
Solution 2-
SimpleDateFormat time_format = new SimpleDateFormat("HH:mm:ss.SSS");
String timeComp = time_format.format(Calendar.getInstance().getTime());
output - 15:57:25.518
To answer part of it, accessing the millisecond component is done like this:
long mill = Calendar.getInstance().getTime();
I don't know what you want to do with the specifics, but you could use the java.text.SimpleDateFormat class if it is for text output.
You can call the getTimeInMillis() function on a Calendar object to get the time in milliseconds. You can call get(Calendar.MILLISECOND) on a calendar object to get the milliseconds of the second. If you want to display the time from a Date or Calendar object, use the DateFormat class. Example: DateFormat.getTimeInstance().format(now). There is also a SimpleDateFormat class that you can use.
To get just the time using Joda-Time, use the org.joda.time.LocalTime class as described in this question, Joda-Time, Time without date.
As for comparing dates only while effectively ignoring time, in Joda-Time call the withTimeAtStartOfDay() method on each DateTime instance to set an identical time value. Here is some example code using Joda-Time 2.3, similar to what I posted on another answer today.
// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
// Joda-Time - The popular alternative to Sun/Oracle's notoriously bad date, time, and calendar classes bundled with Java 7 and earlier.
// http://www.joda.org/joda-time/
// Joda-Time will become outmoded by the JSR 310 Date and Time API introduced in Java 8.
// JSR 310 was inspired by Joda-Time but is not directly based on it.
// http://jcp.org/en/jsr/detail?id=310
// By default, Joda-Time produces strings in the standard ISO 8601 format.
// https://en.wikipedia.org/wiki/ISO_8601
// Capture one moment in time.
org.joda.time.DateTime now = new org.joda.time.DateTime();
System.out.println("Now: " + now);
// Calculate approximately same time yesterday.
org.joda.time.DateTime yesterday = now.minusDays(1);
System.out.println("Yesterday: " + yesterday);
// Compare dates. A DateTime includes time (hence the name).
// So effectively eliminate the time by setting to start of day.
Boolean isTodaySameDateAsYesterday = now.withTimeAtStartOfDay().isEqual(yesterday.withTimeAtStartOfDay());
System.out.println("Is today same date as yesterday: " + isTodaySameDateAsYesterday);
org.joda.time.DateTime halloweenInUnitedStates = new org.joda.time.DateTime(2013, 10, 31, 0, 0);
Boolean isFirstMomentSameDateAsHalloween = now.withTimeAtStartOfDay().isEqual(halloweenInUnitedStates.withTimeAtStartOfDay());
System.out.println("Is now the same date as Halloween in the US: " + isFirstMomentSameDateAsHalloween);
If all you're worried about is getting it into a String for display or saving, then just create a SimpleDateFormat that only displays the time portion, like new SimpleDateFormat("HH:mm:ss"). The date is still in the Date object, of course, but you don't care.
If you want to do arithmetic on it, like take two Date objects and find how many seconds apart they are while ignoring the date portion, so that "2009-09-01 11:00:00" minus "1941-12-07 09:00:00" equals 2 hours, then I think you need to use a solution like Jherico's: get the long time and take it module 1 day.
Why do you want to separate them? If you mean to do any arithmetic with the time portion, you will quickly get into trouble. If you pull out 11:59pm and add a minute, now that your time and day are separate, you've screwed yourself--you'll have an invalid time and an incorrect date.
If you just want to display them, then applying various simple date format's should get you exactly what you want.
If you want to manipulate the date, I suggest you get the long values and base everything off of that. At any point you can take that long and apply a format to get the minutes/hours/seconds to display pretty easily.
But I'm just a little concerned with the concept of manipulating day and time separately, seems like opening a can o' worms. (Not to even mention time zone problems!).
I'm fairly sure this is why Java doesn't have an easy way to do this.
Find below a solution which employs Joda Time and supports time zones.
So, you will obtain date and time (into currentDate and currentTime) in the currently configured timezone in the JVM.
Please notice that Joda Time does not support leap seconds. So, you can be some 26 or 27 seconds off the true value. This probably will only be solved in the next 50 years, when the accumulated error will be closer to 1 min and people will start to care about it.
See also: https://en.wikipedia.org/wiki/Leap_second
/**
* This class splits the current date/time (now!) and an informed date/time into their components:
* <lu>
* <li>schedulable: if the informed date/time is in the present (now!) or in future.</li>
* <li>informedDate: the date (only) part of the informed date/time</li>
* <li>informedTime: the time (only) part of the informed date/time</li>
* <li>currentDate: the date (only) part of the current date/time (now!)</li>
* <li>currentTime: the time (only) part of the current date/time (now!)</li>
* </lu>
*/
public class ScheduleDateTime {
public final boolean schedulable;
public final long millis;
public final java.util.Date informedDate;
public final java.util.Date informedTime;
public final java.util.Date currentDate;
public final java.util.Date currentTime;
public ScheduleDateTime(long millis) {
final long now = System.currentTimeMillis();
this.schedulable = (millis > -1L) && (millis >= now);
final TimeZoneUtils tz = new TimeZoneUtils();
final java.util.Date dmillis = new java.util.Date( (millis > -1L) ? millis : now );
final java.time.ZonedDateTime zdtmillis = java.time.ZonedDateTime.ofInstant(dmillis.toInstant(), java.time.ZoneId.systemDefault());
final java.util.Date zdmillis = java.util.Date.from(tz.tzdate(zdtmillis));
final java.util.Date ztmillis = new java.util.Date(tz.tztime(zdtmillis));
final java.util.Date dnow = new java.util.Date(now);
final java.time.ZonedDateTime zdtnow = java.time.ZonedDateTime.ofInstant(dnow.toInstant(), java.time.ZoneId.systemDefault());
final java.util.Date zdnow = java.util.Date.from(tz.tzdate(zdtnow));
final java.util.Date ztnow = new java.util.Date(tz.tztime(zdtnow));
this.millis = millis;
this.informedDate = zdmillis;
this.informedTime = ztmillis;
this.currentDate = zdnow;
this.currentTime = ztnow;
}
}
public class TimeZoneUtils {
public java.time.Instant tzdate() {
final java.time.ZonedDateTime zdtime = java.time.ZonedDateTime.now();
return tzdate(zdtime);
}
public java.time.Instant tzdate(java.time.ZonedDateTime zdtime) {
final java.time.ZonedDateTime zddate = zdtime.truncatedTo(java.time.temporal.ChronoUnit.DAYS);
final java.time.Instant instant = zddate.toInstant();
return instant;
}
public long tztime() {
final java.time.ZonedDateTime zdtime = java.time.ZonedDateTime.now();
return tztime(zdtime);
}
public long tztime(java.time.ZonedDateTime zdtime) {
final java.time.ZonedDateTime zddate = zdtime.truncatedTo(java.time.temporal.ChronoUnit.DAYS);
final long millis = zddate.until(zdtime, java.time.temporal.ChronoUnit.MILLIS);
return millis;
}
}
tl;dr
LocalTime lt = myUtilDate.toInstant().atZone( ZoneId.of( "America/Montreal" ) ).toLocalTime() ;
Avoid old date-time classes
You are using old legacy date-time classes. They are troublesome and confusing; avoid them.
Instead use java.time classes. These supplant the old classes as well as the Joda-Time library.
Convert
Convert your java.util.Date to an Instant.
The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds.
Instant instant = myUtilDate.toInstant();
Time Zone
Apply a time zone. Time zone is crucial. For any given moment the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while also being “yesterday” in Montréal Québec.
Apply a ZoneId to get a ZonedDateTime object.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );
Local… types
The LocalDate class represents a date-only value without time-of-day and without time zone. Likewise, the LocalTime represents a time-of-day without a date and without a time zone. You can think of these as two components which along with a ZoneId make up a ZonedDateTime. You can extract these from a ZonedDateTime.
LocalDate ld = zdt.toLocalDate();
LocalTime lt = zdt.toLocalTime();
Strings
If your goal is merely generating Strings for presentation to the user, no need for the Local… types. Instead, use DateTimeFormatter to generate strings representing only the date-portion or the time-portion. That class is smart enough to automatically localize while generating the String.
Specify a Locale to determine (a) the human language used for translating name of day, name of month, and such, and (b) the cultural norms for deciding issues such as abbreviation, capitalization, punctuation, and such.
Locale l = Locale.CANADA_FRENCH ; // Or Locale.US, Locale.ITALY, etc.
DateTimeFormatter fDate = DateTimeFormatter.ofLocalizedDate( FormatStyle.MEDIUM ).withLocale( locale );
String outputDate = zdt.format( fDate );
DateTimeFormatter fTime = DateTimeFormatter.ofLocalizedTime( FormatStyle.MEDIUM ).withLocale( locale );
String outputTime = zdt.format( fTime );
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the old troublesome 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.