There is requirement to see if some date (ex: expiry date) is greater than or equal to today. Presently JODA time library has been used to achieve this simple comparison. Even some post are recommending that like this.
But recently found some problem with timezones. Date exists in PST and when converted to LocalDate following conversion comes false at 5:00 pm PST, when it should be true -
LocalDate now = LocalDate.fromDateFields(new Date()); // Current date in PST
LocalDate expiryDate = LocalDate.fromDateFields(expiresOn); // expiresOn is java.util.Date
boolean notExpired = expiryDate.isEqual(now) || expiryDate.isAfter(now);
When looked closely, LocalDate expiryDate was using UTC chronology. So at 5:00pm PST, when variable expiryDate contains contains "2021-01-16", variable now becomes "2021-01-17"
Please recommend, what is the better-way to deal with this problem.
I am trying to understand, what special advantages I might achieve by using joda time, because the same compassion can be done using SimpleDateFormatter.
The date-time API of java.util and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern date-time API.
For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7.
If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
Learn about the modern date-time API from Trail: Date Time.
LocalDate uses JVM's timezone by default
Whenever timezone is involved, make sure to specify the same while creating an instance of LocalDate. A LocalDate uses JVM's timezone by default and you should never compare a LocalDate from one timezone to that of another without converting both of them in the same timezone (the recommended one is UTC). Same is the case with LocalDateTime. Instead of using LocalDate, you should do all processing with objects which have both date and time (e.g. LocalDateTime) and if required you can derive the LocalDate from them.
Also, the java.util.Date object simply represents the number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT (or UTC). When you print an object of java.util.Date, its toString method returns the date-time in the JVM's timezone, calculated from this milliseconds value.
Therefore, if you are deriving expiryDate from a java.util.Date object, it is essentially date-time in UTC.
You can convert now-in-PST and expiryDate into java.time.Instant and compare them. A java.time.Instant is an instantaneous point on the UTC time-line.
Demo using the modern date-time API:
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Calendar;
import java.util.Date;
public class Main {
public static void main(String[] args) {
LocalDateTime nowInPST = LocalDateTime.now(ZoneId.of("America/Los_Angeles"));
System.out.println(nowInPST);
// Convert it to date in UTC
Instant nowInPSTConvertedToInstant = nowInPST.atZone(ZoneId.of("America/Los_Angeles"))
.withZoneSameInstant(ZoneId.of("Etc/UTC"))
.toInstant();
// Some java.util.Date
Calendar calendar = Calendar.getInstance();
calendar.set(2020, 0, 10, 10, 10, 10);
Date date = calendar.getTime();
Instant expiry = date.toInstant();
System.out.println(nowInPSTConvertedToInstant.isBefore(expiry));
}
}
Output:
2021-01-17T10:58:38.490041
false
Note: Check the following notice at the Home Page of Joda-Time
Joda-Time is the de facto standard date and time library for Java
prior to Java SE 8. Users are now asked to migrate to java.time
(JSR-310).
Simplify your expression
The following statement
boolean notExpired = expiryDate.isEqual(now) || expiryDate.isAfter(now);
can be simplified as
boolean notExpired = !expiryDate.isBefore(now);
You should consider two APIs:
Joda-Time that you have been using until now is a good library, but in maintenance mode.
The chief developer of Joda-Time, Stephen Colebourne, went on to develop java.time, the modern Java date and time API, drawing on lessons from good and not so good experiences from Joda-Time.
It’s not perfectly clear from your question. I am assuming that expiration has been recorded in UTC and appears to be one day early because it is looked at in Pacific Time. So I am showing you how to keep everything in UTC so comparisons make sense and are accurate.
Joda-Time
System.setProperty("user.timezone", "America/Vancouver");
Date expiresOn = new Date(1_610_841_600_000L); // Jan 17 UTC
System.out.println(expiresOn);
LocalDate now = LocalDate.now(DateTimeZone.UTC);
System.out.println(now);
LocalDate expiryDate = new DateTime(expiresOn, DateTimeZone.UTC).toLocalDate();
System.out.println(expiryDate);
boolean notExpired = expiryDate.isEqual(now) || expiryDate.isAfter(now);
System.out.println("Expired? " + (notExpired ? "No" : "Yes"));
Output when running now:
Sat Jan 16 16:00:00 PST 2021
2021-01-17
2021-01-17
Expired? No
The Joda-Time home page says:
Note that Joda-Time is considered to be a largely “finished” project.
No major enhancements are planned. If using Java SE 8, please migrate
to java.time (JSR-310).
java.time
LocalDate now = LocalDate.now(ZoneOffset.UTC);
System.out.println(now);
LocalDate expiryDate = expiresOn.toInstant()
.atOffset(ZoneOffset.UTC)
.toLocalDate();
System.out.println(expiryDate);
boolean notExpired = expiryDate.isEqual(now) || expiryDate.isAfter(now);
System.out.println("Expired? " + (notExpired ? "No" : "Yes"));
2021-01-17
2021-01-17
Expired? No
A note on taste
My taste is for avoiding unnecessary negations in variable names (and elsewhere). I’d find it simpler to do:
boolean expired = expiryDate.isBefore(now);
System.out.println("Expired? " + expired);
Expired? false
Links
Joda-Time Home
Oracle tutorial: Date Time explaining how to use java.time.
Related
Is there a way to check if a java Date object is Monday? I see you can with a Calendar object, but date? I'm also using US-eastern date and time if that changes indexing of monday
Something like this will work:
Calendar cal = Calendar.getInstance();
cal.setTime(theDate);
boolean monday = cal.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY;
You can use Calendar object.
Set your date to calendar object using setTime(date)
Example:
calObj.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY
EDIT: As Jon Skeet suggested, you need to set TimeZone to Calendar object to make sure it works perfect for the timezone.
The question doesn't make sense without two extra pieces of information: a time zone and a calendar system.
A Date object just represents an instant in time. It happens to be Wednesday in the Gregorian calendar in my time zone - but for some folks to the east of me, it's already Thursday. In other calendar systems, there may not even be such a concept of "Monday" etc.
The calendar system part is probably not a problem, but you will need to work out which time zone you're interested in.
You can then create a Calendar object and set both the time zone and the instant represented - or, better, you could use Joda Time which is a much better date/time API. You'll still need to think about the same questions, but your code will be clearer.
You should use Calendar object for these checks. Date has weak timezones support. In one timezone this Date can be Monday, and in another timezone it is still Sunday.
java.time
The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.
Also, quoted below is a notice from the home page of Joda-Time:
Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this project.
Solution using java.time, the modern Date-Time API:
Use Instant to represent a moment:
Instant instant = Instant.now();
System.out.println(instant); // A sample output: 2021-07-03T09:07:37.984Z
An Instant represents an instantaneous point on the timeline in UTC. The Z in the output is the timezone designator for a zero-timezone offset. It stands for Zulu and specifies the Etc/UTC timezone (which has the timezone offset of +00:00 hours).
However, if you have got an object of java.util.Date, convert it to Instant e.g.
Date date = new Date(); // A sample date
Instant instant = date.toInstant();
Convert Instant to ZonedDateTime representing Date-Time in your timezone e.g.
ZonedDateTime zdt = instant.atZone(ZoneId.of("America/New_York"));
Check if the Date-Time falls on Monday e.g.
System.out.println(zdt.getDayOfWeek() == DayOfWeek.SUNDAY);
Demo:
import static java.time.DayOfWeek.SUNDAY;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class Main {
public static void main(String[] args) {
Instant instant = Instant.now();
ZonedDateTime zdt = instant.atZone(ZoneId.of("America/New_York"));
System.out.println(zdt.getDayOfWeek() == SUNDAY);
}
}
Output:
false
ONLINE DEMO
Learn more about the modern Date-Time API from Trail: Date Time.
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
Ok, so I've pretty much tried everything. I bet it's something really simple but I can't seem to get a hold of it.
The server sends me the time, which is epoch. However when I put this into a date object it seems to automatically pick up the time zone and it adds +3 to the server time. So if the gmt time is 00.00, it says its 03.00.
I also need to add a timezone of my own. Let's say the epoch time is 00.00 again, it should read 10.00 after I add the timezone.
any help would be much appreciated. Thank you
"It seems to add" - I suspect you're using Date.toString() which does indeed use the local time zone. The Date object itself is effectively in UTC though. Use DateFormat to perform the conversion to a string instead, and you can specify which time zone to use. You may also need to use Calendar - it depends what you're trying to do.
(Alternatively, use Joda Time in the first place, which is a better API. It may be a little bulky for your Android project though. I wouldn't be surprised if there were a "Joda Time lite" project around somewhere for precisely this sort of thing...)
EDIT: Quick sample, although it's not entirely clear what you need...
long millis = getMillisFromServer();
Date date = new Date(millis);
DateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
format.setTimeZone(customTimeZone);
String formatted = format.format(date);
java.time
The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.
Also, quoted below is a notice from the home page of Joda-Time:
Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this project.
Solution using java.time, the modern Date-Time API:
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class Main {
public static void main(String[] args) {
long millis = 1316391494L;
Instant instant = Instant.ofEpochMilli(millis);
System.out.println(instant);
// The same instant at a specific timezone
ZonedDateTime zdt = instant.atZone(ZoneId.of("Australia/Brisbane"));
System.out.println(zdt);
}
}
Output:
1970-01-16T05:39:51.494Z
1970-01-16T15:39:51.494+10:00[Australia/Brisbane]
ONLINE DEMO
Learn more about the modern Date-Time API from Trail: Date Time.
What went wrong with your code?
A java.util.Date object simply represents an instant on the timeline — a wrapper around the number of milliseconds since the UNIX epoch (January 1, 1970, 00:00:00 GMT). Since it does not hold any timezone information, its toString function applies the JVM's timezone to return a String in the format, EEE MMM dd HH:mm:ss zzz yyyy, derived from this milliseconds value. To get the String representation of the java.util.Date object in a different format and timezone, you need to use SimpleDateFormat with the desired format and the applicable timezone e.g.
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
public class Main {
public static void main(String[] args) {
long millis = 1316391494L;
Date date = new Date(millis);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX[zzzz]", Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
String strDateUtc = sdf.format(date);
System.out.println(strDateUtc);
sdf.setTimeZone(TimeZone.getTimeZone("Australia/Brisbane"));
String strDateBrisbane = sdf.format(date);
System.out.println(strDateBrisbane);
}
}
Output:
1970-01-16T05:39:51.494Z[Coordinated Universal Time]
1970-01-16T15:39:51.494+10:00[Australian Eastern Standard Time]
ONLINE DEMO
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
What is the minimum date value in Java?
Don't forget that Date constructor happily accepts negative values.
Date date = new Date(Long.MIN_VALUE);
returns
Sun Dec 02 22:47:04 BDT 292269055
I guess that's about the time of Big Bang dinosaurs :)
EDIT
As martin clayton answered, you can use the Calendar class to check the era. This will output 0 which stands for BCE:
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date(Long.MIN_VALUE));
System.out.println(calendar.get(Calendar.ERA));
If you are talking about java.util.Date as a timestamp you can do this
Date d = new Date(0L) and you will see this represents Thu Jan 01 01:00:00 GMT 1970
As tulskiy has pointed out it is possible to pass a negative value to the Date constructor. If we do this and use a date format that includes the era we can see:
Date d = new Date(Long.MIN_VALUE);
DateFormat df = new SimpleDateFormat("EEE, d MMM yyyy G HH:mm:ss Z");
System.out.println(df.format(d));
displays: Sun, 2 Dec 292269055 BC 16:47:04 +0000
The other Answers may be correct but use outmoded classes.
java.time
The old date-time classes (java.util.Date/.Calendar etc.) have been supplanted by the java.time framework built into Java 8 and later.
The java.time classes are inspired by Joda-Time, defined by JSR 310, extended by the ThreeTen-Extra project, back-ported to Java 6 & 7 by the ThreeTen-Backport project, and adapted to Android in the ThreeTenABP project. See Tutorial.
For a moment on the timeline in UTC with a resolution of nanoseconds, use Instant. Given an offset-from-UTC, use OffsetDateTime. For a time zone (offset + rules for anomalies), use ZonedDateTime, but by its nature has no defined minimum, nor does ZoneId. For a date-only value without time-of-day and without time zone, use LocalDate. For a time-of-day only value without date and without time zone, use LocalTime. For date-time without time zone, use LocalDateTime.
Instant.MIN = -1000000000-01-01T00:00Z
OffsetDateTime.MIN = -999999999-01-01T00:00:00+18:00
LocalDate.MIN = -999999999-01-01
LocalTime.MIN = 00:00
LocalDateTime.MIN = -999999999-01-01T00:00:00
Year.MIN_VALUE = -999,999,999
ZoneOffset.MIN = -18:00 (but -12:00 in practice)
Caution: Be wary of using these values as some kind of flag or special meaning. Many other software libraries and databases may not support these extreme values.
For a flag or special meaning such as a non-null "no value available", I suggest picking an arbitrary moment but avoid going to such extreme reaches either backward or forward in time. Perhaps the Unix epoch reference date, the first moment of 1970 in UTC, 1970-01-01T00:00:00Z. Defined as a constant in Java: Instant.EPOCH
It's the same as for the Calendar classes.
Try this:
Date d = new Date( Long.MIN_VALUE );
System.out.println( d );
You'll see:
Sun Dec 02 16:47:04 GMT 292269055
But the default date format doesn't include the era - which is BCE for this date.
LocalDateTime MIN defines the minimum supported LocalDateTime, '-999999999-01-01T00:00:00'.
This is the local date-time of midnight at the start of the minimum date.
public static final LocalDateTime MIN; this is the MIN syntax;
import java.time.LocalDateTime;
public class Main {
public static void main(String[] args) {
LocalDateTime a = LocalDateTime.MIN;
System.out.println(a);
}
}
Since Date is marked as Deprecated, i thought there should be another way to get around this, so i looked at some of the methods, and i found this way
You can aslo use Long.MIN_VALUE, at the time i wrote this, i hadn't searched for it, and even/so i didn't remember it.
Edited
It is mentioned in the comment that not whole class is deprecated, and still is usable, but some of its functionalities are deprecated, so you may reconsider some of those...
Note: By the time I wrote it, I used Java 8, and now we have long array of Java versions since then in which they even may reconsider methods, or change behavior or etc. that I'm not aware of, since now I program in another language.
I have a Date object which represents a UTC time. When I use the method getTime() to get the long value of this object, the value returned corresponds to our local time (central US). What is the correct way to get the value back which corresponds to the original UTC time?
Thanks
tl;dr
Instant.now()
…and…
Instant.ofEpochMilli( n )
…and…
instant.toEpochMilli()
Date is always in UTC
When I use the method getTime() to get the long value of this object, the value returned corresponds to our local time (central US).
No, the value returned from Date::getTime() always corresponds to UTC (virtually the same thing as GMT in this context). To quote the class doc:
Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT represented by this Date object.
So your Question is nonsensical in that a Date is already in UTC. No need to “get the value back which corresponds to the original UTC time”,
You may be confusing the behavior of getTime with that of the toString method. The toString method annoyingly and confusingly applies the current default time zone in the process of generating the String. So the string output appears with a time zone while in fact there is no time zone to be set or gotten from the Date itself. (There actually is a zone deep within the Date but that is irrelevant to this discussion here. This class is a confusing mess!)
java.time
The modern way to do this is using java.time classes.
Instant
The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
Get the current moment.
Instant instant = Instant.now();
You can convert a Date to its modern replacement by calling one of the new conversion methods added to the old date-time classes. Just call toInstant, quite easy.
Instant instant = myJavaUtilDate.toInstant();
I do not recommend at all using a count-from-epoch number as a way of tracking time. Stick with the java.time objects instead. When outside Java, serialize to text use the ISO 8601 formats.
But if you must, you can extract a count of milliseconds since epoch of 1970-01-01T00:00:00Z. Note that this may involve data loss! An Instant has a finer resolution of nanoseconds. So going to milliseconds may lop off a fraction of the fraction of a second.
long millisecondsSinceEpoch = instant.toEpochMilli(); // Caution: Possible data-loss in going from nanoseconds to milliseconds.
Going the other direction, from a count to an Instant.
Instant instant = Instant.ofEpochMilli( millisecondsSinceEpoch ) ;
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 and 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 SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
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. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
The DateFormat class has a method for setting your preferred time zone, and there's a time zone class that has a setting for UTC time.
So, for example,
SimpleDateFormat sdf = new SimpleDateFormat();
sdf.setTimeZone(new SimpleTimeZone(SimpleTimeZone.UTC_TIME, "UTC"));
Date yourUtcDate = sdf.parse(yourOriginalDate);
java.util.Date has no concept of timezone. It simply holds time relative to epoch, which is Jan 1 1970 00:00:00 UTC. Date is a model, separate from the view. When you display the date, the concept of timezone then is applied. Date's toString() displays a human readable date in the default timezone. You can either use a DateFormat to display a Date in a different timezone (such as UTC), or change the JVM's default timezone.
getTime() returns "the number of milliseconds since January 1, 1970, 00:00:00 GMT", nothing more, nothing less (obviously, you have to create it correctly). You can format it however you want, starting with e.g. the GregorianCalendar(TimeZone) constructor.
Most of the Date class functions are deprecated as they are now shifted in Calendar class.
Here is code to get UTC time from Calendar.
Date date = new Date(timeStamp);
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
calendar.setTime(date);
Here is the sample code to get the year, month, etc.
System.out.println(calendar.get(Calendar.YEAR));
System.out.println(calendar.get(Calendar.MONTH));
Calendar also has support for many other useful information like, TIME, DAY_OF_MONTH, etc. Here the documentation listing all of them Please note that the month are 0 based. January is 0th month.
LocalDateTime now = LocalDateTime.now(Clock.systemUTC());
Instant instant = now.atZone(ZoneId.systemDefault()).toInstant();
Date formattedDate = Date.from(instant);
return formattedDate;
I need today's date - and zero anything else (" 05/06/08 00:00:00 ")
I've tried
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR, 0);
Date date1 = calendar.getTime();
System.out.println(date1);
Run: (This is seriously messed up)
If the hour on the computer is < 12:00 at noon : Sun Mar 08 00:44:39 IST 2009
If the hour on the computer is > 12:00 at noon : Sun Mar 08 12:46:53 IST 2009
So I gave this up.
All the Date's setters are deprecated (except the epoch time) - so I don't want to use them either
The only thing I could think of is
Calendar calendar = Calendar.getInstance();
SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
String sDate = dateFormat.format(calendar.getTime());
Date today = dateFormat.parse(sDate);
But this is such a lame code I can't bring myself to write it.
Any other option?
Thanks!
I use this:
public static Date startOfDay(Date date) {
Calendar dCal = Calendar.getInstance();
dCal.setTime(date);
dCal.set(Calendar.HOUR_OF_DAY, 0);
dCal.set(Calendar.MINUTE, 0);
dCal.set(Calendar.SECOND, 0);
dCal.set(Calendar.MILLISECOND, 0);
return dCal.getTime();
}
My standard advice for Java date/time questions: don't use java.util.{Calendar,Date}. Use Joda Time. That way you can represent a date as a date (with no associated time zone), instead of a date/time. Or you could use a DateMidnight if that's what you want to represent. (Be careful of combinations of time zone and date where there is no midnight though...)
What do you need to use the Date with? If you can get away with changing to use Joda throughout, that's great. Otherwise, you can use Joda to do what you want and then convert to milliseconds (and then to java.util.Date) when you really need to.
(Michael's solution when using Date/Calendar is fine if you really want to stick within a broken API... but I can't overstate how much better Joda is...)
You should use HOUR_OF_DAY instead of HOUR and combine it with MINUTE and SECOND also.
import java.util.Calendar;
import static java.util.Calendar.HOUR_OF_DAY;
import static java.util.Calendar.MINUTE;
import static java.util.Calendar.SECOND;
import static java.util.Calendar.MILLISECOND;
public class Today {
public static void main( String [] args ) {
Calendar cal = Calendar.getInstance();
cal.set( HOUR_OF_DAY, 0 );
cal.set( MINUTE, 0 );
cal.set( SECOND, 0 );
cal.set( MILLISECOND, 0 );
System.out.println( cal.getTime() );
}
}
The results you are getting are due to HOUR is used to AM/PM while HOUR_OF_DAY is 24 hrs.
HOUR_OF_DAY:
Field number for get and set indicating the hour of the day. HOUR_OF_DAY is used for the 24-hour clock. E.g., at 10:04:15.250 PM the HOUR_OF_DAY is 22.
HOUR:
Field number for get and set indicating the hour of the morning or afternoon. HOUR is used for the 12-hour clock (0 - 11). Noon and midnight are represented by 0, not by 12. E.g., at 10:04:15.250 PM the HOUR is 10.
The time component is not just hours (and Calendar.HOUR is, as you have noticed, AM/PM).
You need to set all of the time fields to 0: HOUR_OF_DAY, MINUTE, SECOND, MILLISECOND.
See Apache's commons-lang DateUtils.truncate()
java.time
The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.
Also, quoted below is a notice from the home page of Joda-Time:
Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this project.
Solution using java.time, the modern Date-Time API:
The modern Date-Time API has many types which truly represent a date or time or date-time in a specific timezone. You can choose from the following options as per your specific requirement:
If you are looking for a type that represents a date without a timezone, you can use LocalDate.now. The good news is that its variant, LocalDate#now(ZoneId) returns the current date from the system clock in the specified time-zone.
If you are looking for an object that represents a date without a timezone, and with time units set to zero, you can call LocalDate#atStartOfDay on the object obtained with Option#1.
If you are looking for an Instant representing the Date-Time object obtained with Option#2, you can attach this object with ZoneId.of("Etc/UTC") using LocalDateTime#atZone to obtain a ZonedDateTime and convert the same into an Instant using ZonedDateTime#toInstant.
Demo:
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class Main {
public static void main(String[] args) {
LocalDate todayInSystemTz = LocalDate.now();
System.out.println(todayInSystemTz);
LocalDate todayInIndia = LocalDate.now(ZoneId.of("Asia/Kolkata"));
System.out.println(todayInIndia);
LocalDateTime todayInSystemTzWithZeroTimeUnits = todayInSystemTz.atStartOfDay();
System.out.println(todayInSystemTzWithZeroTimeUnits);
ZonedDateTime todayInUtcWithZeroTimeUnits = todayInSystemTzWithZeroTimeUnits.atZone(ZoneId.of("Etc/UTC"));
System.out.println(todayInUtcWithZeroTimeUnits);
Instant instant = todayInUtcWithZeroTimeUnits.toInstant();
System.out.println(instant);
// Can I represent the obtained Instant in India?
System.out.println(instant.atZone(ZoneId.of("Asia/Kolkata")));
// Can I represent the obtained Instant in New York?
System.out.println(instant.atZone(ZoneId.of("America/New_York")));
}
}
Output:
2021-06-20
2021-06-20
2021-06-20T00:00
2021-06-20T00:00Z[Etc/UTC]
2021-06-20T00:00:00Z
2021-06-20T05:30+05:30[Asia/Kolkata]
2021-06-19T20:00-04:00[America/New_York]
ONLINE DEMO
The Z in the output is the timezone designator for zero-timezone offset. It stands for Zulu and specifies the Etc/UTC timezone (which has the timezone offset of +00:00 hours).
For any reason, if you need to convert this object of Instant to an object of java.util.Date**, you can do so as follows:
Date date = Date.from(instant);
Learn more about the modern Date-Time API from Trail: Date Time.
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
**
A java.util.Date object simply represents the number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT (or UTC). Since it does not hold any timezone information, its toString function applies the JVM's timezone to return a String in the format, EEE MMM dd HH:mm:ss zzz yyyy, derived from this milliseconds value. To get the String representation of the java.util.Date object in a different format and timezone, you need to use SimpleDateFormat with the desired format and the applicable timezone e.g.
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getTimeZone("America/New_York"));
String strDateNewYork = sdf.format(date);
sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
String strDateUtc = sdf.format(date);
As mentioned above you should use
Calendar.HOUR_OF_DAY
As opposed to
Calendar.HOUR
Also you need to clear out the other fields (Calendar.MINUTE, Calendar.SECOND, and Calendar.MILLISECOND) by setting them to zero.
Sorry there's no easy way here. A pain, and that's why they're working on a new API for Java 7 I believe based on Joda Time.
...or you can do it the hacker way:
long MS_PER_DAY = 86400000L;
Date dateTime=new Date();
long offset = TimeZone.getDefault().getOffset(dateTime.getTime());
Date date= new Date(((dateTime.getTime()+offset)/MS_PER_DAY)*MS_PER_DAY-offset);
I know this is a very old question, no longer active, but it came to be on the top when I searched Google.
While all advise is very good, I can't believe no one simply answered:
Date date = new Date(System.currentTimeMillis());
System.out.println(date);
Which returns effectively, today's date.
Why the string manipulation?
Can you not just set the values you need on the Calendar object before converting to a Date using getTime()?
Another vote for JodaTime.
java.util.Date and Calendar are so bad they are broken. (And SimpleDateFormat is rubbish too!)
For what it's worth, Java 7 will include a new date time library based strongly around JodaTime.