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
Related
I have a DatePicker element ("DPstart").
I want to save the timestamp (in milliseconds) of midnight at the string "newStartDate", Without regard to the time zone of the user.
How can I do this?
DatePicker DPstart = (DatePicker) findViewById(R.id.datePickerStart);
Calendar calendar = new GregorianCalendar(DPstart.getYear(), DPstart.getMonth(), DPstart.getDayOfMonth());
long DPS = calendar.getTimeInMillis();
String newStartDate = Long.toString(DPS);
ThreeTenABP
My suggestion is you skip the outdated classes Calendar and GregorianCalendar and start using the modern Java date and time API. It’s much nicer to work with. Even when DatePicker return values are designed for use with the old classes. And even when the modern API isn’t native on very many Android phones yet (that will come).
You will need to get the ThreeTenABP library. Useful question: How to use ThreeTenABP in Android Project. Then your code could go like this:
long dps = LocalDate.of(dpStart.getYear(), Month.values()[dpStart.getMonth()],
dpStart.getDayOfMonth())
.atStartOfDay(ZoneOffset.UTC)
.toInstant()
.toEpochMilli();
String newStartDate = Long.toString(dps);
Picking 4 September 2017, the result will be 1504483200000.
My way of converting from the date picker’s 0-based month to LocalDate’s more human 1-based month is a bit peculiar. If you find it simpler just to add 1, that will work too:
long dps = LocalDate.of(dpStart.getYear(), dpStart.getMonth() + 1, dpStart.getDayOfMonth())
// …
I have renamed your variables to conform with Java coding conventions. They say a variable name should begin with a lowercase letter.
As an aside, I believe that accepted best practices for storing timestamps is you store either the Instant you get from toInstant() or its string representation (from toString()) rather than the millisecond value. Millisecond values are very hard for most of us to interpret, for example when we see them in the debugger. Instant values are readily understood, at least roughly what time they refer to. An even better human-readable format would be the string representation of the LocalDate, it looks like 2017-09-04. The string representations of both Instant and LocalDate conform with ISO 8601.
The outdated solution
If you definitely don’t want to rely in a third party library like ThreeTenABP, even temporarily until the modern date and time API comes to Android, I believe the solution with Calendar is (1) make sure it uses UTC time zone (2) clear the hours, minutes, seconds and milliseconds to make sure you get the time at midnight:
Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
calendar.clear();
calendar.set(dpStart.getYear(), dpStart.getMonth(), dpStart.getDayOfMonth());
The result is the same as above.
public Long timestampFromString(String format,String time){
// format example "yyyy.MM.dd hh:mm"
DateFormat formatter = new SimpleDateFormat(format);
Date date = null;
try {
date = formatter.parse(time);
return date.getTime();
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
public String stringFromTimestamp(String format,Long time){
Timestamp timestamp = new Timestamp(time);
return new SimpleDateFormat(format).format(timestamp);
}
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
I try to get the date of yesterday. So I write the next function:
public String getYestrday() {
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date date = new Date();
return dateFormat.format(date.getDate() - 1);
}
But it gives me the next warning:
The method getDate() from the type Date is deprecated
and it doesn't do it work.
Thank you for your help.
Date#getDate() is a deprecated method after JDK 1.1. You should be using Calendar class instead to manipulate dates.
From API:
Prior to JDK 1.1, the class Date had two additional functions. It
allowed the interpretation of dates as year, month, day, hour, minute,
and second values. It also allowed the formatting and parsing of date
strings. Unfortunately, the API for these functions was not amenable
to internationalization. As of JDK 1.1, the Calendar class should be
used to convert between dates and time fields and the DateFormat class
should be used to format and parse date strings. The corresponding
methods in Date are deprecated.
It is also clearly documented in the API using Date#getDate() to use Calendar#get(Calendar.DATE);
Deprecated. As of JDK version 1.1, replaced by
Calendar.get(Calendar.DAY_OF_MONTH)
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DATE, -1);
return dateFormat.format(cal.getTime());
Use java.util.Calendar to do it. Or try JODA.
you can use Calendar class to do the same task:
Calendar c = new Calendar();
//c.add(Calendar.DAY_OF_MONTH, -1);
Date d = c.getTime();
Avoid java.util.Date & .Calendar
The accepted answer is correct. However, the java.util.Date and .Calendar classes are notoriously troublesome. Avoid them. Use either Joda-Time or the new java.time package (in Java 8).
Separate Date-Time Manipulation From Formatting
Also, the code in the question mixes date-time work with formatting. Separate those tasks to make your code clear and testing/debugging easier.
Time Zone
Time zone is critical in date-time work. If you ignore the issue, the JVM's default time zone will be applied. A better practice is to always specify rather than rely on default. Even when you want the default, explicitly call getDefault.
The beginning of the day is defined by the time zone. A new day dawns earlier in Paris than in Montréal. So if by "yesterday" you mean the first moment of that day, then you should (a) specify a time zone, and (b) call withTimeAtStartOfDay.
Joda-Time
Example code in Joda-Time 2.3.
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" );
DateTime today = DateTime.now( timeZone );
Or convert from a java.util.Date object.
DateTime today = new DateTime( myJUDate, timeZone );
Subtract a day to get to yesterday (or day before).
DateTime yesterday = today.minusDays( 1 );
DateTime yesterdayStartOfDay = today.minusDays( 1 ).withTimeAtStartOfDay();
By default, Joda-Time and java.time parse/generate strings in ISO 8601 format.
String output = yesterdayStartOfDay.toString(); // Uses ISO 8601 format by default.
Use a formatter for a full date as four digit year, two digit month of year, and two digit day of month (yyyy-MM-dd). Such a formatter is already defined in Joda-Time.
String outputDatePortion = ISODateFormat.date().print( yesterdayStartOfDay );
Following works for me
int date = Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
I want to get the previous day (24 hours) from the current time.
e.g if current time is Date currentTime = new Date();
2011-04-25 12:15:31:562 GMT
How to determine time i.e
2011-04-24 12:15:31:562 GMT
You can do that using Calendar class:
Calendar cal = Calendar.getInstance();
cal.setTime ( date ); // convert your date to Calendar object
int daysToDecrement = -1;
cal.add(Calendar.DATE, daysToDecrement);
date = cal.getTime(); // again get back your date object
I would suggest you use Joda Time to start with, which is a much nicer API. Then you can use:
DateTime yesterday = new DateTime().minusDays(1);
Note that "this time yesterday" isn't always 24 hours ago though... you need to think about time zones etc. You may want to use LocalDateTime or Instant instead of DateTime.
please checkout this here:
Java Date vs Calendar
Calendar cal=Calendar.getInstance();
cal.setTime(date); //not sure if date.getTime() is needed here
cal.add(Calendar.DAY_OF_MONTH, -1);
Date newDate = cal.getTime();
24 hours and 1 day are not the same thing. But you do both using Calendar:
Calendar c = Calendar.getInstance();
c.setTime(new Date());
c.add(Calendar.DATE, -1);
Date d = c.getTime();
If you are going back 24 hours, you would use Calendar.HOUR_OF_DAY
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.temporal.ChronoUnit;
public class Main {
public static void main(String[] args) {
Instant now = Instant.now();
System.out.println("Now: " + now);
Instant yesterday = now.minus(1, ChronoUnit.DAYS);
System.out.println("Yesterday: " + yesterday);
}
}
Output of a sample run:
Now: 2021-07-16T20:40:24.402592Z
Yesterday: 2021-07-15T20:40:24.402592Z
ONLINE DEMO
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(odt.toInstant());
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.
Anyone know a simple way using Java calendar to subtract X days from a date?
I have not been able to find any function which allows me to directly subtract X days from a date in Java. Can someone point me to the right direction?
Taken from the docs here:
Adds or subtracts the specified amount of time to the given calendar field, based on the calendar's rules. For example, to subtract 5 days from the current time of the calendar, you can achieve it by calling:
Calendar calendar = Calendar.getInstance(); // this would default to now
calendar.add(Calendar.DAY_OF_MONTH, -5).
You could use the add method and pass it a negative number. However, you could also write a simpler method that doesn't use the Calendar class such as the following
public static void addDays(Date d, int days)
{
d.setTime( d.getTime() + (long)days*1000*60*60*24 );
}
This gets the timestamp value of the date (milliseconds since the epoch) and adds the proper number of milliseconds. You could pass a negative integer for the days parameter to do subtraction. This would be simpler than the "proper" calendar solution:
public static void addDays(Date d, int days)
{
Calendar c = Calendar.getInstance();
c.setTime(d);
c.add(Calendar.DATE, days);
d.setTime( c.getTime().getTime() );
}
Note that both of these solutions change the Date object passed as a parameter rather than returning a completely new Date. Either function could be easily changed to do it the other way if desired.
Anson's answer will work fine for the simple case, but if you're going to do any more complex date calculations I'd recommend checking out Joda Time. It will make your life much easier.
FYI in Joda Time you could do
DateTime dt = new DateTime();
DateTime fiveDaysEarlier = dt.minusDays(5);
tl;dr
LocalDate.now().minusDays( 10 )
Better to specify time zone.
LocalDate.now( ZoneId.of( "America/Montreal" ) ).minusDays( 10 )
Details
The old date-time classes bundled with early versions of Java, such as java.util.Date/.Calendar, have proven to be troublesome, confusing, and flawed. Avoid them.
java.time
Java 8 and later supplants those old classes with the new java.time framework. See Tutorial. Defined by JSR 310, inspired by Joda-Time, and extended by theThreeTen-Extra project. The ThreeTen-Backport project back-ports the classes to Java 6 & 7; the ThreeTenABP project to Android.
The Question is vague, not clear if it asks for a date-only or a date-time.
LocalDate
For a date-only, without time-of-day, use the LocalDate class. Note that a time zone in crucial in determining a date such as "today".
LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) );
LocalDate tenDaysAgo = today.minusDays( 10 );
ZonedDateTime
If you meant a date-time, then use the Instant class to get a moment on the timeline in UTC. From there, adjust to a time zone to get a ZonedDateTime object.
Instant now = Instant.now(); // UTC.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
ZonedDateTime tenDaysAgo = zdt.minusDays( 10 );
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.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, 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 (<26), 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.
int x = -1;
Calendar cal = ...;
cal.add(Calendar.DATE, x);
See java.util.Calendar#add(int,int)
Instead of writing my own addDays as suggested by Eli, I would prefer to use DateUtils from Apache. It is handy especially when you have to use it multiple places in your project.
The API says:
addDays(Date date, int amount)
Adds a number of days to a date returning a new object.
Note that it returns a new Date object and does not make changes to the previous one itself.
I faced the same challenge where I needed to go back by 1 day (should be able to roll back by one even if previous day falls into previous year or months).
I did following, basically subtracted by 24 hours for 1 day.
someDateInGregorianCalendar.add(Calendar.HOUR, -24);
Alternatively, I could also do
GregorianCalendar cal = new GregorianCalendar();
cal.set(Calendar.YEAR, 2021);
cal.set(Calendar.MONTH, 0);
cal.set(Calendar.DATE, 1);
System.out.println("Original: " + cal.getTime());
cal.add(Calendar.DATE, -1);
System.out.println("After adding DATE: " + cal.getTime());
OUTPUT:
Original: Fri Jan 01 15:08:33 CET 2021
After adding DATE: Thu Dec 31 15:08:33 CET 2020
It can be done easily by the following
Calendar calendar = Calendar.getInstance();
// from current time
long curTimeInMills = new Date().getTime();
long timeInMills = curTimeInMills - 5 * (24*60*60*1000); // `enter code here`subtract like 5 days
calendar.setTimeInMillis(timeInMills);
System.out.println(calendar.getTime());
// from specific time like (08 05 2015)
calendar.set(Calendar.DAY_OF_MONTH, 8);
calendar.set(Calendar.MONTH, (5-1));
calendar.set(Calendar.YEAR, 2015);
timeInMills = calendar.getTimeInMillis() - 5 * (24*60*60*1000);
calendar.setTimeInMillis(timeInMills);
System.out.println(calendar.getTime());
I believe a clean and nice way to perform subtraction or addition of any time unit (months, days, hours, minutes, seconds, ...) can be achieved using the java.time.Instant class.
Example for subtracting 5 days from the current time and getting the result as Date:
new Date(Instant.now().minus(5, ChronoUnit.DAYS).toEpochMilli());
Another example for subtracting 1 hour and adding 15 minutes:
Date.from(Instant.now().minus(Duration.ofHours(1)).plus(Duration.ofMinutes(15)));
If you need more accuracy, Instance measures up to nanoseconds. Methods manipulating nanosecond part:
minusNano()
plusNano()
getNano()
Also, keep in mind, that Date is not as accurate as Instant. My advice is to stay within the Instant class, when possible.
Someone recommended Joda Time so - I have been using this CalendarDate class http://calendardate.sourceforge.net
It's a somewhat competing project to Joda Time, but much more basic at only 2 classes. It's very handy and worked great for what I needed since I didn't want to use a package bigger than my project. Unlike the Java counterparts, its smallest unit is the day so it is really a date (not having it down to milliseconds or something). Once you create the date, all you do to subtract is something like myDay.addDays(-5) to go back 5 days. You can use it to find the day of the week and things like that.
Another example:
CalendarDate someDay = new CalendarDate(2011, 10, 27);
CalendarDate someLaterDay = today.addDays(77);
And:
//print 4 previous days of the week and today
String dayLabel = "";
CalendarDate today = new CalendarDate(TimeZone.getDefault());
CalendarDateFormat cdf = new CalendarDateFormat("EEE");//day of the week like "Mon"
CalendarDate currDay = today.addDays(-4);
while(!currDay.isAfter(today)) {
dayLabel = cdf.format(currDay);
if (currDay.equals(today))
dayLabel = "Today";//print "Today" instead of the weekday name
System.out.println(dayLabel);
currDay = currDay.addDays(1);//go to next day
}
Eli Courtwright second solution is wrong, it should be:
Calendar c = Calendar.getInstance();
c.setTime(date);
c.add(Calendar.DATE, -days);
date.setTime(c.getTime().getTime());