Related
I'm trying to make a code that tells me how many days left for me to go college, but I am not able to do it with the current date. I can easily make it by setting a date, but I want the current date, so I have to use the calendar method, but can't do math using it.
My code:
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
Calendar calendar = Calendar.getInstance();
Date start = sdf.parse("10/06/2022");
System.out.println(start - calendar.getTime());
tl;dr
ChronoUnit.DAYS.between(
LocalDate.now( ZoneId.of( "Pacific/Auckland" ) ) ,
LocalDate.parse( "10/06/2022" , DateTimeFormatter.ofPattern( "dd/MM/uuuu" ) )
)
Details
You are using terrible date-time classes that were years ago supplanted by the modern java.time classes defined in JSR 310. Never use Date/Calendar.
Also, you are attempting to use a date-time class representing a date with time-of-day as seen in UTC (offset of zero) to hold a date-only value. Square peg, round hole.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd/MM/uuuu" ) ;
LocalDate graduationDate = LocalDate.parse( "10/06/2022" , f ) ;
Determine today's date. That requires a time zone. For any given moment, the date varies around the globe by time zone.
ZoneId z = ZoneId.of( "Asia/Tokyo" ) ; // Or ZoneId.systemDefault()
LocalDate today = LocalDate.now( z ) ;
Calculate elapsed time using java.time.temporal.ChronoUnit.
long days = ChronoUnit.DAYS.between( today , graduationDate ) ;
See this code run live at IdeOne.com.
graduationDate: 2022-06-10
today: 2022-03-05
days: 97
Tip: Learn about the ISO 8601 standard for exchanging date-time values as text.
Calendar calendar = Calendar.getInstance();
Calendar collegeDate = Calendar.getInstance();
collegeDate.set(Calendar.DATE,10);
collegeDate.set(Calendar.MONTH, 5);
collegeDate.set(Calendar.YEAR, 2022);
System.out.println(Duration.between(calendar.toInstant(), collegeDate.toInstant()).toDays());
You can try this
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
Calendar calendar = Calendar.getInstance();
Date start = sdf.parse("10/06/2022");
long dif = Math.abs(calendar.getTimeInMillis() - start.getTime());
long result = TimeUnit.DAYS.convert(dif, TimeUnit.MILLISECONDS);
System.out.println(result);
I'm working with a date in this format: yyyy-mm-dd.
How can I increment this date by one day?
Something like this should do the trick:
String dt = "2008-01-01"; // Start date
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Calendar c = Calendar.getInstance();
c.setTime(sdf.parse(dt));
c.add(Calendar.DATE, 1); // number of days to add
dt = sdf.format(c.getTime()); // dt is now the new date
UPDATE (May 2021): This is a really outdated answer for old, old Java. For Java 8 and above, see https://stackoverflow.com/a/20906602/314283
Java does appear to be well behind the eight-ball compared to C#. This utility method shows the way to do in Java SE 6 using the Calendar.add method (presumably the only easy way).
public class DateUtil
{
public static Date addDays(Date date, int days)
{
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.add(Calendar.DATE, days); //minus number would decrement the days
return cal.getTime();
}
}
To add one day, per the question asked, call it as follows:
String sourceDate = "2012-02-29";
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date myDate = format.parse(sourceDate);
myDate = DateUtil.addDays(myDate, 1);
java.time
On Java 8 and later, the java.time package makes this pretty much automatic. (Tutorial)
Assuming String input and output:
import java.time.LocalDate;
public class DateIncrementer {
static public String addOneDay(String date) {
return LocalDate.parse(date).plusDays(1).toString();
}
}
I prefer to use DateUtils from Apache. Check this http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/time/DateUtils.html. It is handy especially when you have to use it multiple places in your project and would not want to write your one liner method for this.
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.
SimpleDateFormat dateFormat = new SimpleDateFormat( "yyyy-MM-dd" );
Calendar cal = Calendar.getInstance();
cal.setTime( dateFormat.parse( inputString ) );
cal.add( Calendar.DATE, 1 );
Construct a Calendar object and call add(Calendar.DATE, 1);
Java 8 added a new API for working with dates and times.
With Java 8 you can use the following lines of code:
// parse date from yyyy-mm-dd pattern
LocalDate januaryFirst = LocalDate.parse("2014-01-01");
// add one day
LocalDate januarySecond = januaryFirst.plusDays(1);
Take a look at Joda-Time (https://www.joda.org/joda-time/).
DateTimeFormatter parser = ISODateTimeFormat.date();
DateTime date = parser.parseDateTime(dateString);
String nextDay = parser.print(date.plusDays(1));
Please note that this line adds 24 hours:
d1.getTime() + 1 * 24 * 60 * 60 * 1000
but this line adds one day
cal.add( Calendar.DATE, 1 );
On days with a daylight savings time change (25 or 23 hours) you will get different results!
you can use Simple java.util lib
Calendar cal = Calendar.getInstance();
cal.setTime(yourDate);
cal.add(Calendar.DATE, 1);
yourDate = cal.getTime();
Date today = new Date();
SimpleDateFormat formattedDate = new SimpleDateFormat("yyyyMMdd");
Calendar c = Calendar.getInstance();
c.add(Calendar.DATE, 1); // number of days to add
String tomorrow = (String)(formattedDate.format(c.getTime()));
System.out.println("Tomorrows date is " + tomorrow);
This will give tomorrow's date. c.add(...) parameters could be changed from 1 to another number for appropriate increment.
If you are using Java 8, then do it like this.
LocalDate sourceDate = LocalDate.of(2017, Month.MAY, 27); // Source Date
LocalDate destDate = sourceDate.plusDays(1); // Adding a day to source date.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); // Setting date format
String destDate = destDate.format(formatter)); // End date
If you want to use SimpleDateFormat, then do it like this.
String sourceDate = "2017-05-27"; // Start date
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Calendar calendar = Calendar.getInstance();
calendar.setTime(sdf.parse(sourceDate)); // parsed date and setting to calendar
calendar.add(Calendar.DATE, 1); // number of days to add
String destDate = sdf.format(calendar.getTime()); // End date
Since Java 1.5 TimeUnit.DAYS.toMillis(1) looks more clean to me.
SimpleDateFormat dateFormat = new SimpleDateFormat( "yyyy-MM-dd" );
Date day = dateFormat.parse(string);
// add the day
Date dayAfter = new Date(day.getTime() + TimeUnit.DAYS.toMillis(1));
long timeadj = 24*60*60*1000;
Date newDate = new Date (oldDate.getTime ()+timeadj);
This takes the number of milliseconds since epoch from oldDate and adds 1 day worth of milliseconds then uses the Date() public constructor to create a date using the new value. This method allows you to add 1 day, or any number of hours/minutes, not only whole days.
In Java 8 simple way to do is:
Date.from(Instant.now().plusSeconds(SECONDS_PER_DAY))
It's very simple, trying to explain in a simple word.
get the today's date as below
Calendar calendar = Calendar.getInstance();
System.out.println(calendar.getTime());// print today's date
calendar.add(Calendar.DATE, 1);
Now set one day ahead with this date by calendar.add method which takes (constant, value). Here constant could be DATE, hours, min, sec etc. and value is the value of constant. Like for one day, ahead constant is Calendar.DATE and its value are 1 because we want one day ahead value.
System.out.println(calendar.getTime());// print modified date which is tomorrow's date
Thanks
startCalendar.add(Calendar.DATE, 1); //Add 1 Day to the current Calender
In java 8 you can use java.time.LocalDate
LocalDate parsedDate = LocalDate.parse("2015-10-30"); //Parse date from String
LocalDate addedDate = parsedDate.plusDays(1); //Add one to the day field
You can convert in into java.util.Date object as follows.
Date date = Date.from(addedDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
You can formate LocalDate into a String as follows.
String str = addedDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
With Java SE 8 or higher you should use the new Date/Time API
int days = 7;
LocalDate dateRedeemed = LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/YYYY");
String newDate = dateRedeemed.plusDays(days).format(formatter);
System.out.println(newDate);
If you need to convert from java.util.Date to java.time.LocalDate, you may use this method.
public LocalDate asLocalDate(Date date) {
Instant instant = date.toInstant();
ZonedDateTime zdt = instant.atZone(ZoneId.systemDefault());
return zdt.toLocalDate();
}
With a version prior to Java SE 8 you may use Joda-Time
Joda-Time provides a quality replacement for the Java date and time
classes and is the de facto standard date and time library for Java
prior to Java SE 8
int days = 7;
DateTime dateRedeemed = DateTime.now();
DateTimeFormatter formatter = DateTimeFormat.forPattern("dd/MM/uuuu");
String newDate = dateRedeemed.plusDays(days).toString(formatter);
System.out.println(newDate);
Apache Commons already has this DateUtils.addDays(Date date, int amount) http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/time/DateUtils.html#addDays%28java.util.Date,%20int%29 which you use or you could go with the JodaTime to make it more cleaner.
Just pass date in String and number of next days
private String getNextDate(String givenDate,int noOfDays) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
Calendar cal = Calendar.getInstance();
String nextDaysDate = null;
try {
cal.setTime(dateFormat.parse(givenDate));
cal.add(Calendar.DATE, noOfDays);
nextDaysDate = dateFormat.format(cal.getTime());
} catch (ParseException ex) {
Logger.getLogger(GR_TravelRepublic.class.getName()).log(Level.SEVERE, null, ex);
}finally{
dateFormat = null;
cal = null;
}
return nextDaysDate;
}
If you want to add a single unit of time and you expect that other fields to be incremented as well, you can safely use add method. See example below:
SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd");
Calendar cal = Calendar.getInstance();
cal.set(1970,Calendar.DECEMBER,31);
System.out.println(simpleDateFormat1.format(cal.getTime()));
cal.add(Calendar.DATE, 1);
System.out.println(simpleDateFormat1.format(cal.getTime()));
cal.add(Calendar.DATE, -1);
System.out.println(simpleDateFormat1.format(cal.getTime()));
Will Print:
1970-12-31
1971-01-01
1970-12-31
Use the DateFormat API to convert the String into a Date object, then use the Calendar API to add one day. Let me know if you want specific code examples, and I can update my answer.
Try this method:
public static Date addDay(int day) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
calendar.add(Calendar.DATE, day);
return calendar.getTime();
}
It's simple actually.
One day contains 86400000 milliSeconds.
So first you get the current time in millis from The System by usingSystem.currentTimeMillis() then
add the 84000000 milliSeconds and use the Date Class to generate A date format for the milliseconds.
Example
String Today = new Date(System.currentTimeMillis()).toString();
String Today will be 2019-05-9
String Tommorow = new Date(System.currentTimeMillis() + 86400000).toString();
String Tommorow will be 2019-05-10
String DayAfterTommorow = new Date(System.currentTimeMillis() + (2 * 86400000)).toString();
String DayAfterTommorow will be 2019-05-11
You can use this package from "org.apache.commons.lang3.time":
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date myNewDate = DateUtils.addDays(myDate, 4);
Date yesterday = DateUtils.addDays(myDate, -1);
String formatedDate = sdf.format(myNewDate);
If you are using Java 8, java.time.LocalDate and java.time.format.DateTimeFormatter can make this work quite simple.
public String nextDate(String date){
LocalDate parsedDate = LocalDate.parse(date);
LocalDate addedDate = parsedDate.plusDays(1);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-mm-dd");
return addedDate.format(formatter);
}
The highest voted answer uses legacy java.util date-time API which was the correct thing to do in 2009 when the question was asked. In March 2014, java.time API supplanted the error-prone legacy date-time API. Since then, it is strongly recommended to use this modern date-time API.
I'm working with a date in this format: yyyy-mm-dd
You have used the wrong letter for the month, irrespective of whether you are using the legacy parsing/formatting API or the modern one. The letter m is used for minute-of-hour and the correct letter for month-of-year is M.
yyyy-MM-dd is the default format of java.time.LocalDate
The java.time API is based on ISO 8601 standards and therefore it does not require specifying a DateTimeFormatter explicitly to parse a date-time string if it is already in ISO 8601 format. Similarly, the toString implementation of a java.time type returns a string in ISO 8601 format. Check LocalDate#parse and LocalDate#toString for more information.
Ways to increment a local date by one day
There are three options:
LocalDate#plusDays(long daysToAdd)
LocalDate#plus(long amountToAdd, TemporalUnit unit): It has got some additional capabilities e.g. you can use it to increment a local date by days, weeks, months, years etc.
LocalDate#plus(TemporalAmount amountToAdd): You can specify a Period (or any other type implementing the TemporalAmount) to add.
Demo:
import java.time.Instant;
import java.time.LocalDate;
import java.time.Period;
import java.time.temporal.ChronoUnit;
public class Main {
public static void main(String[] args) {
// Parsing
LocalDate ldt = LocalDate.parse("2020-10-20");
System.out.println(ldt);
// Incrementing by one day
LocalDate oneDayLater = ldt.plusDays(1);
System.out.println(oneDayLater);
// Alternatively
oneDayLater = ldt.plus(1, ChronoUnit.DAYS);
System.out.println(oneDayLater);
oneDayLater = ldt.plus(Period.ofDays(1));
System.out.println(oneDayLater);
String desiredString = oneDayLater.toString();
System.out.println(desiredString);
}
}
Output:
2020-10-20
2020-10-21
2020-10-21
2020-10-21
2020-10-21
How to switch from the legacy to the modern date-time API?
You can switch from the legacy to the modern date-time API using Date#toInstant on a java-util-date instance. Once you have an Instant, you can easily obtain other date-time types of java.time API. An Instant represents a moment in time and is independent of a time-zone i.e. it represents a date-time in UTC (often displayed as Z which stands for Zulu-time and has a ZoneOffset of +00:00).
Demo:
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.Date;
public class Main {
public static void main(String[] args) {
Date date = new Date();
Instant instant = date.toInstant();
System.out.println(instant);
ZonedDateTime zdt = instant.atZone(ZoneId.of("Asia/Kolkata"));
System.out.println(zdt);
OffsetDateTime odt = instant.atOffset(ZoneOffset.of("+05:30"));
System.out.println(odt);
// Alternatively, using time-zone
odt = instant.atZone(ZoneId.of("Asia/Kolkata")).toOffsetDateTime();
System.out.println(odt);
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneId.of("Asia/Kolkata"));
System.out.println(ldt);
// Alternatively,
ldt = instant.atZone(ZoneId.of("Asia/Kolkata")).toLocalDateTime();
System.out.println(ldt);
}
}
Output:
2022-11-12T12:52:18.016Z
2022-11-12T18:22:18.016+05:30[Asia/Kolkata]
2022-11-12T18:22:18.016+05:30
2022-11-12T18:22:18.016+05:30
2022-11-12T18:22:18.016
2022-11-12T18:22:18.016
Learn more about the modern Date-Time API from Trail: Date Time.
Let's clarify the use case: You want to do calendar arithmetic and start/end with a java.util.Date.
Some approaches:
Convert to string and back with SimpleDateFormat: This is an inefficient solution.
Convert to LocalDate: You would lose any time-of-day information.
Convert to LocalDateTime: This involves more steps and you need to worry about timezone.
Convert to epoch with Date.getTime(): This is efficient but you are calculating with milliseconds.
Consider using java.time.Instant:
Date _now = new Date();
Instant _instant = _now.toInstant().minus(5, ChronoUnit.DAYS);
Date _newDate = Date.from(_instant);
You can do this just in one line.
e.g to add 5 days
Date newDate = Date.from(Date().toInstant().plus(5, ChronoUnit.DAYS));
to subtract 5 days
Date newDate = Date.from(Date().toInstant().minus(5, ChronoUnit.DAYS));
I need to create a new Calendar object that contains the current date but the time needs to be set from a given String of format HH:mm:ss.
I create a new calendar object with current date and time and then use a SimpleDateFormat object to parse the string and set the time from that one but that only overwrites the calendar object with the parsed time and Jan 1 1970:
def currentTime = new java.util.Date();
Calendar calendar1 = Calendar.getInstance();
calendar1.setTime(currentTime);
java.util.Date inTime = new SimpleDateFormat("HH:mm:ss").parse(initialTime);
calendar1.setTime(inTime);
Is there a way to get the values of Hour, Minute, Seconds and Milliseconds from the Date object to use it with calendar.set(Calendar.HOUR_OF_DAY, hour), etc.?
tl;dr
GregorianCalendar.from( // Converting from modern java.time class to troublesome legacy class. Do so only if you must. Otherwise use only the java.time classes.
ZonedDateTime.of( // Modern java.time class representing a moment, a point on the timeline, with an assigned time zone through which to see the wall-clock time used by the people of a particular region.
LocalDate.now( ZoneId.of( “Pacific/Auckland” ) ) , // The current date in a particular time zone. For any given moment, the date varies around the globe by zone.
LocalTime.of( 12 , 34 , 56 ) , // Specify your desired time-of-day.
ZoneId.of( “Pacific/Auckland” ) // Assign a time zone for which the date and time is intended.
)
)
java.time
The modern approach uses the java.time classes.
ZoneId z = ZoneId.of( “America/Montreal” ) ;
LocalDate ld = LocalDate.now( z ) ;
LocalTime lt = LocalTime.of( 12 , 34 , 56 ) ; // 12:34:56
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;
You can extract the time-of-day (or date) from an existing ZonedDateTime.
LocalTime lt = zdt.toLocalTime() ;
LocalDate ld = zdt.toLocalDate() ;
Best to avoid the troublesome old legacy date-time classes added before Java 8. But if you must, you can convert between the modern and legacy classes. Call on new methods added to the old classes.
GregorianCalendar gc = GregorianCalendar.from( zdt ) ; // If you must, but better to avoid the troublesome old legacy classes.
Not sure if this helps you.
String hhmmss = "10:20:30";
String[] parts = hhmmss.split(":");
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(parts[0]));
cal.set(Calendar.MINUTE, Integer.parseInt(parts[1]));
cal.set(Calendar.SECOND, Integer.parseInt(parts[2]));
Calendar objet Time is a java.util.Date object with the standard format. You can not set date with a specific format to your calendar.
To get the Date details (Hours, Minutes ...) try :
final Date date = new Date(); // your date
final Calendar cal = Calendar.getInstance();
cal.setTime(date);
final int year = cal.get(Calendar.YEAR);
final int month = cal.get(Calendar.MONTH);
final int day = cal.get(Calendar.DAY_OF_MONTH);
final int hour = cal.get(Calendar.HOUR_OF_DAY);
final int minute = cal.get(Calendar.MINUTE);
final int second = cal.get(Calendar.SECOND);
I am trying to set the year of a java.util.Date.
he time stamp I need to parse does not include the year so I did this:
private static final SimpleDateFormat logTimeStampFormat =
new SimpleDateFormat("MMM dd HH:mm:ss.SSS");
boolean isAfterRefDate (String line, Date refDate) {
try {
Date logTimeStamp = logTimeStampFormat.parse(line);
logTimeStamp.setYear(2012); // But this is deprecated!
return logTimeStamp.after(refDate);
} catch (ParseException e) {
// Handle exception
}
}
To avoid using a deprecated method, I do like this:
private static final SimpleDateFormat logTimeStampFormat =
new SimpleDateFormat("MMM dd HH:mm:ss.SSS");
private static Calendar cal = Calendar.getInstance();
boolean isAfterRefDate (String line, Date refDate) {
try {
Date logTimeStamp = logTimeStampFormat.parse(line);
cal.setTime(logTimeStamp);
cal.set(Calendar.YEAR, 2012);
logTimeStamp = cal.getTime();
return logTimeStamp.after(refDate);
} catch (ParseException e) {
// Handle exception
}
}
I just don't think that this is the best way to solve this problem. I have to first set the calendar object properly and then get the date object back from it while earlier I could just modify the date object directly.
Can someone suggest a better approach?
Can someone suggest a better approach.
Sure - try to avoid using Date and Calendar in the first place. Use Joda Time instead, which is much better.
Setting the year on a Date is an inherently ambiguous operation - what time zone is this year meant to be? What would you expect to happen if you're setting a year of 2013 on a previous date of February 29th 2012?
Using Joda Time will make your code much clearer in terms of what kind of data you're really expecting. You can always convert to/from Date and Calendar at API boundaries if you really need to.
java.time
Can someone suggest a better approach?
Yes, use the java.time classes.
The Answer by Jon Skeet was correct but is now outdated, as the Joda-Time team advises migration to the java.time classes.
MonthDay & LocalTime
We can parse that input string as two separate objects, a MonthDay and a LocalTime. The first is obviously a month and a day-of-month but without any year so it is not a complete date. The second represents a time-of-day but without any date and without any time zone.
String input = "Sep 21 12:34:56.123";
DateTimeFormatter f = DateTimeFormatter.ofPattern ( "MMM dd HH:mm:ss.SSS" );
MonthDay md = MonthDay.parse ( input , f );
LocalTime lt = LocalTime.parse ( input , f );
System.out.println ( "md: " + md + " | lt: " + lt );
md: --09-21 | lt: 12:34:56.123
LocalDateTime
We can add in a year, stir altogether, and get a LocalDateTime.
LocalDateTime ldt = LocalDateTime.of( ld , lt );
ZonedDateTime
This is still not an actual moment, not a point on the timeline. Without the context of an offset-from-UTC or a time zone, a LocalDateTime has no meaning.
Apply a ZoneId to get a ZonedDateTime. Now we have a meaningful moment, a point on the timeline.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ldt.atZone( z );
How to obtain the start time and end time of a day?
code like this is not accurate:
private Date getStartOfDay(Date date) {
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DATE);
calendar.set(year, month, day, 0, 0, 0);
return calendar.getTime();
}
private Date getEndOfDay(Date date) {
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DATE);
calendar.set(year, month, day, 23, 59, 59);
return calendar.getTime();
}
It is not accurate to the millisecond.
Java 8
public static Date atStartOfDay(Date date) {
LocalDateTime localDateTime = dateToLocalDateTime(date);
LocalDateTime startOfDay = localDateTime.with(LocalTime.MIN);
return localDateTimeToDate(startOfDay);
}
public static Date atEndOfDay(Date date) {
LocalDateTime localDateTime = dateToLocalDateTime(date);
LocalDateTime endOfDay = localDateTime.with(LocalTime.MAX);
return localDateTimeToDate(endOfDay);
}
private static LocalDateTime dateToLocalDateTime(Date date) {
return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
}
private static Date localDateTimeToDate(LocalDateTime localDateTime) {
return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
}
Update: I've added these 2 methods to my Java Utility Classes here
DateUtils.atStartOfDay
DateUtils.atEndOfDay
It is in the Maven Central Repository at:
<dependency>
<groupId>com.github.rkumsher</groupId>
<artifactId>utils</artifactId>
<version>1.3</version>
</dependency>
Java 7 and Earlier
With Apache Commons
public static Date atEndOfDay(Date date) {
return DateUtils.addMilliseconds(DateUtils.ceiling(date, Calendar.DATE), -1);
}
public static Date atStartOfDay(Date date) {
return DateUtils.truncate(date, Calendar.DATE);
}
Without Apache Commons
public Date atEndOfDay(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.HOUR_OF_DAY, 23);
calendar.set(Calendar.MINUTE, 59);
calendar.set(Calendar.SECOND, 59);
calendar.set(Calendar.MILLISECOND, 999);
return calendar.getTime();
}
public Date atStartOfDay(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
return calendar.getTime();
}
tl;dr
LocalDate // Represents an entire day, without time-of-day and without time zone.
.now( // Capture the current date.
ZoneId.of( "Asia/Tokyo" ) // Returns a `ZoneId` object.
) // Returns a `LocalDate` object.
.atStartOfDay( // Determines the first moment of the day as seen on that date in that time zone. Not all days start at 00:00!
ZoneId.of( "Asia/Tokyo" )
) // Returns a `ZonedDateTime` object.
Start of day
Get the full length of the today as seen in a time zone.
Using Half-Open approach, where the beginning is inclusive while the ending is exclusive. This approach solves the flaw in your code that fails to account for the very last second of the day.
ZoneId zoneId = ZoneId.of( "Africa/Tunis" ) ;
LocalDate today = LocalDate.now( zoneId ) ;
ZonedDateTime zdtStart = today.atStartOfDay( zoneId ) ;
ZonedDateTime zdtStop = today.plusDays( 1 ).atStartOfDay( zoneId ) ;
zdtStart.toString() = 2020-01-30T00:00+01:00[Africa/Tunis]
zdtStop.toString() = 2020-01-31T00:00+01:00[Africa/Tunis]
See the same moments in UTC.
Instant start = zdtStart.toInstant() ;
Instant stop = zdtStop.toInstant() ;
start.toString() = 2020-01-29T23:00:00Z
stop.toString() = 2020-01-30T23:00:00Z
If you want the entire day of a date as seen in UTC rather than in a time zone, use OffsetDateTime.
LocalDate today = LocalDate.now( ZoneOffset.UTC ) ;
OffsetDateTime odtStart = today.atTime( OffsetTime.MIN ) ;
OffsetDateTime odtStop = today.plusDays( 1 ).atTime( OffsetTime.MIN ) ;
odtStart.toString() = 2020-01-30T00:00+18:00
odtStop.toString() = 2020-01-31T00:00+18:00
These OffsetDateTime objects will already be in UTC, but you can call toInstant if you need such objects which are always in UTC by definition.
Instant start = odtStart.toInstant() ;
Instant stop = odtStop.toInstant() ;
start.toString() = 2020-01-29T06:00:00Z
stop.toString() = 2020-01-30T06:00:00Z
Tip: You may be interested in adding the ThreeTen-Extra library to your project to use its Interval class to represent this pair of Instant objects. This class offers useful methods for comparison such as abuts, overlaps, contains, and more.
Interval interval = Interval.of( start , stop ) ;
interval.toString() = 2020-01-29T06:00:00Z/2020-01-30T06:00:00Z
Half-Open
The answer by mprivat is correct. His point is to not try to obtain end of a day, but rather compare to "before start of next day". His idea is known as the "Half-Open" approach where a span of time has a beginning that is inclusive while the ending is exclusive.
The current date-time frameworks of Java (java.util.Date/Calendar and Joda-Time) both use milliseconds from the epoch. But in Java 8, the new JSR 310 java.time.* classes use nanoseconds resolution. Any code you wrote based on forcing the milliseconds count of last moment of day would be incorrect if switched to the new classes.
Comparing data from other sources becomes faulty if they employ other resolutions. For example, Unix libraries typically employ whole seconds, and databases such as Postgres resolve date-time to microseconds.
Some Daylight Saving Time changes happen over midnight which might further confuse things.
Joda-Time 2.3 offers a method for this very purpose, to obtain first moment of the day: withTimeAtStartOfDay(). Similarly in java.time, LocalDate::atStartOfDay.
Search StackOverflow for "joda half-open" to see more discussion and examples.
See this post, Time intervals and other ranges should be half-open, by Bill Schneider.
Avoid legacy date-time classes
The java.util.Date and .Calendar classes are notoriously troublesome. Avoid them.
Use java.time classes. The java.time framework is the official successor of the highly successful Joda-Time library.
java.time
The java.time framework is built into Java 8 and later. Back-ported to Java 6 & 7 in the ThreeTen-Backport project, further adapted to Android in the ThreeTenABP project.
An Instant is a moment on the timeline in UTC with a resolution of nanoseconds.
Instant instant = Instant.now();
Apply a time zone to get the wall-clock time for some locality.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
To get the first moment of the day go through the LocalDate class and its atStartOfDay method.
ZonedDateTime zdtStart = zdt.toLocalDate().atStartOfDay( zoneId );
Using Half-Open approach, get first moment of following day.
ZonedDateTime zdtTomorrowStart = zdtStart.plusDays( 1 );
Currently the java.time framework lacks an Interval class as described below for Joda-Time. However, the ThreeTen-Extra project extends java.time with additional classes. This project is the proving ground for possible future additions to java.time. Among its classes is Interval. Construct an Interval by passing a pair of Instant objects. We can extract an Instant from our ZonedDateTime objects.
Interval today = Interval.of( zdtStart.toInstant() , zdtTomorrowStart.toInstant() );
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.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
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. Hibernate 5 & JPA 2.2 support java.time.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 brought some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android (26+) bundle implementations of the java.time classes.
For earlier Android (<26), a process known as API desugaring brings a subset of the java.time functionality not originally built into Android.
If the desugaring does not offer what you need, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above) to Android. See How to use ThreeTenABP….
Joda-Time
UPDATE: The Joda-Time project is now in maintenance-mode, and advises migration to the java.time classes. I am leaving this section intact for history.
Joda-Time has three classes to represent a span of time in various ways: Interval, Period, and Duration. An Interval has a specific beginning and ending on the timeline of the Universe. This fits our need to represent "a day".
We call the method withTimeAtStartOfDay rather than set time of day to zeros. Because of Daylight Saving Time and other anomalies the first moment of the day may not be 00:00:00.
Example code using Joda-Time 2.3.
DateTimeZone timeZone = DateTimeZone.forID( "America/Montreal" );
DateTime now = DateTime.now( timeZone );
DateTime todayStart = now.withTimeAtStartOfDay();
DateTime tomorrowStart = now.plusDays( 1 ).withTimeAtStartOfDay();
Interval today = new Interval( todayStart, tomorrowStart );
If you must, you can convert to a java.util.Date.
java.util.Date date = todayStart.toDate();
in getEndOfDay, you can add:
calendar.set(Calendar.MILLISECOND, 999);
Although mathematically speaking, you can't specify the end of a day other than by saying it's "before the beginning of the next day".
So instead of saying, if(date >= getStartOfDay(today) && date <= getEndOfDay(today)), you should say: if(date >= getStartOfDay(today) && date < getStartOfDay(tomorrow)). That is a much more solid definition (and you don't have to worry about millisecond precision).
java.time
Using java.time framework built into Java 8.
import java.time.LocalTime;
import java.time.LocalDateTime;
LocalDateTime now = LocalDateTime.now(); // 2015-11-19T19:42:19.224
// start of a day
now.with(LocalTime.MIN); // 2015-11-19T00:00
now.with(LocalTime.MIDNIGHT); // 2015-11-19T00:00
// end of a day
now.with(LocalTime.MAX); // 2015-11-19T23:59:59.999999999
Java 8 or ThreeTenABP
ZonedDateTime
ZonedDateTime curDate = ZonedDateTime.now();
public ZonedDateTime startOfDay() {
return curDate
.toLocalDate()
.atStartOfDay()
.atZone(curDate.getZone())
.withEarlierOffsetAtOverlap();
}
public ZonedDateTime endOfDay() {
ZonedDateTime startOfTomorrow =
curDate
.toLocalDate()
.plusDays(1)
.atStartOfDay()
.atZone(curDate.getZone())
.withEarlierOffsetAtOverlap();
return startOfTomorrow.minusSeconds(1);
}
// based on https://stackoverflow.com/a/29145886/1658268
LocalDateTime
LocalDateTime curDate = LocalDateTime.now();
public LocalDateTime startOfDay() {
return curDate.atStartOfDay();
}
public LocalDateTime endOfDay() {
return startOfTomorrow.atTime(LocalTime.MAX); //23:59:59.999999999;
}
// based on https://stackoverflow.com/a/36408726/1658268
I hope that helps someone.
Additional way of finding start of day with java8 java.time.ZonedDateTime instead of going through LocalDateTime is simply truncating the input ZonedDateTime to DAYS:
zonedDateTimeInstance.truncatedTo( ChronoUnit.DAYS );
I tried this code and it works well!
final ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
final ZonedDateTime startofDay =
now.toLocalDate().atStartOfDay(ZoneOffset.UTC);
final ZonedDateTime endOfDay =
now.toLocalDate().atTime(LocalTime.MAX).atZone(ZoneOffset.UTC);
For java 8 the following single line statements are working. In this example I use UTC timezone. Please consider to change TimeZone that you currently used.
System.out.println(new Date());
final LocalDateTime endOfDay = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);
final Date endOfDayAsDate = Date.from(endOfDay.toInstant(ZoneOffset.UTC));
System.out.println(endOfDayAsDate);
final LocalDateTime startOfDay = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
final Date startOfDayAsDate = Date.from(startOfDay.toInstant(ZoneOffset.UTC));
System.out.println(startOfDayAsDate);
If no time difference with output. Try: ZoneOffset.ofHours(0)
Another one solution which does not depend on any framework is:
static public Date getStartOfADay(Date day) {
final long oneDayInMillis = 24 * 60 * 60 * 1000;
return new Date(day.getTime() / oneDayInMillis * oneDayInMillis);
}
static public Date getEndOfADay(Date day) {
final long oneDayInMillis = 24 * 60 * 60 * 1000;
return new Date((day.getTime() / oneDayInMillis + 1) * oneDayInMillis - 1);
}
Note that it returns UTC based time
I know it's a bit late, but in case of Java 8, if you are using OffsetDateTime (which offers a lot of advantages, such as TimeZone, Nanoseconds, etc.), you can use the following code:
OffsetDateTime reallyEndOfDay = someDay.withHour(23).withMinute(59).withSecond(59).withNano(999999999);
// output: 2019-01-10T23:59:59.999999999Z
private Date getStartOfDay(Date date) {
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DATE);
calendar.setTimeInMillis(0);
calendar.set(year, month, day, 0, 0, 0);
return calendar.getTime();
}
private Date getEndOfDay(Date date) {
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DATE);
calendar.setTimeInMillis(0);
calendar.set(year, month, day, 23, 59, 59);
return calendar.getTime();
}
calendar.setTimeInMillis(0); gives you accuracy upto milliseconds
Shortest answer, given your timezone being TZ:
LocalDateTime start = LocalDate.now(TZ).atStartOfDay()
LocalDateTime end = start.plusDays(1)
Compare using isAfter() and isBefore() methods, or convert it using toEpochSecond() or toInstant() methods.
The following code takes the OP's original formula, and adjusts for the ms inexactness:
private static Date getStartOfDay() {
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DATE);
calendar.set(year, month, day, 0, 0, 0);
long approximateTimestamp = calendar.getTime().getTime();
long extraMillis = (approximateTimestamp % 1000);
long exactTimestamp = approximateTimestamp - extraMillis;
return new Date(exactTimestamp);
}
private static Date getEndOfDay() {
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DATE);
calendar.set(year, month, day, 23, 59, 59);
long approximateTimestamp = calendar.getTime().getTime();
long extraMillis = (approximateTimestamp % 1000);
long exactTimestamp = approximateTimestamp - extraMillis + 999;
return new Date(exactTimestamp);
}
Unlike many other answers on this thread, it is compatible with older versions of Java and Android APIs.
I had several inconveniences with all the solutions because I needed the type of Instant variable and the Time Zone always interfered changing everything, then combining solutions I saw that this is a good option.
LocalDate today = LocalDate.now();
Instant startDate = Instant.parse(today.toString()+"T00:00:00Z");
Instant endDate = Instant.parse(today.toString()+"T23:59:59Z");
and we have as a result
startDate = 2020-01-30T00:00:00Z
endDate = 2020-01-30T23:59:59Z
I hope it helps you
I think the easiest would be something like:
// Joda Time
DateTime dateTime=new DateTime();
StartOfDayMillis = dateTime.withMillis(System.currentTimeMillis()).withTimeAtStartOfDay().getMillis();
EndOfDayMillis = dateTime.withMillis(StartOfDayMillis).plusDays(1).minusSeconds(1).getMillis();
These millis can be then converted into Calendar,Instant or LocalDate as per your requirement with Joda Time.
public static Date beginOfDay(Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTime();
}
public static Date endOfDay(Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.set(Calendar.HOUR_OF_DAY, 23);
cal.set(Calendar.MINUTE, 59);
cal.set(Calendar.SECOND, 59);
cal.set(Calendar.MILLISECOND, 999);
return cal.getTime();
}
Date date = new Date();
LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
LocalDateTime startOfDay = localDateTime.with(LocalTime.MIN);
LocalDateTime endOfDay = localDateTime.with(LocalTime.MAX);
Timestamp:
Timestamp startTs = Timestamp.valueOf(startOfDay);
Timestamp endTs = Timestamp.valueOf(endOfDay);