This question already has answers here:
How to check if a date is greater than another in Java? [duplicate]
(4 answers)
Closed 2 years ago.
My date time formatter is , "yyyy-MM-DD"
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-DD")
I want to check the date is later than today's date or not. I checked it using this validation.
if(dateFormatter.format(given_Date).compareTo(dateFormatter.format(new Date())) > 0){ ...}
But every time this returns false when the given date is later or not. Can anyone help with this me, please?
tl;dr
You asked:
check the date is later than today's date
LocalDate // Represent a date-only value, without time-of-day and without time zone or offset-from-UTC.
.parse( "2020-01-23" ) // No need to specify formatting pattern when parsing a string in standard ISO 8601 format. Returns a `LocalDate` object.
.isAfter // Compare one `LocalDate` object to another.
(
LocalDate.now // Capture the current date as seen in a particular time zone.
(
ZoneId.of( "Africa/Tunis" ) // or: ZoneId.systemDefault()
) // Returns a `LocalDate` object.
) // Returns `boolean`.
Details
Modern solution uses java.time classes, specifically java.time.LocalDate. Compare with isAfter method. You are using terrible date-time classes that were years ago supplanted by java.time.
No need to specify a formatting pattern. Your input strings comply with the ISO 8601 standard used by default in java.time.
By the way, formatting codes are case-sensitive, and day-of-month is dd rather than the DD you used. So the formatting pattern used here by default is akin to uuuu-MM-dd.
boolean isFuture = LocalDate.parse( "2020-01-23" ).isAfter( LocalDate.now() ) ;
Better to explicitly specify desired/expected time by which to determine today’s date. If omitted, the JVM’s current default time zone is implicitly applied.
boolean isFuture = LocalDate.parse( "2020-01-23" ).isAfter( LocalDate.now( ZoneId.of( "America/Edmonton" ) ) ) ;
If you can work with the variable givenDate as a String there is another way. Check out my code:
import java.util.Calendar;
public class compareDates {
public static void main(String[] args){
Calendar c = Calendar.getInstance();
String givenDate = "2021-01-10";
boolean later = false;
int yr_now = c.get(Calendar.YEAR);
int m_now = c.get(Calendar.MONTH) + 1;
int day_now = c.get(Calendar.DAY_OF_MONTH);
int given_yr = Integer.parseInt(givenDate.substring(0,4));
int given_m = Integer.parseInt(givenDate.substring(5,7));
int given_day = Integer.parseInt(givenDate.substring(8,10));
//is "given date" later than today's date?
if(yr_now > given_yr) {
System.out.print(later);
}
else if (yr_now == given_yr && m_now > given_m){
System.out.print(later);
}
else if (m_now == given_m && day_now >= given_day){
System.out.print(later);
}
else {later = true; System.out.print(later);}
}}
Related
I'm trying to check if a selected dates range by the user is within a range of dates exist in database.
e.g.
User select :
Start date : 24/09/2022
End date : 30/09/2022
Date range in database is :
Start date : 28/09/2022
End date : 30/09/2022
Imagine you have a reservation car between 28/09 → 30/09, if a user wants to reserve this car between 24/09 --> 30/09, then the app should notify them that the car is reserved in that date because it's already reserved between 28--> 30.
My situation is similar to this: Check if a date range is within a date range. Only that question is about C#, and I am coding Java.
My code so far :
boolean isFound = DateHelper.isWithinRange2Dates(
/*ENTERED BY USER*/
string2Date("24/09/2022"),
string2Date("30/09/2022"),
/*IN DATABASE*/
string2Date("28/09/2022"),
string2Date("30/09/2022"));
ToastUtils.showLong(isFound ? "FOUND" : "NOT FOUND");
Methods used :
public static boolean isWithinRange(Date selectedDate, Date startDate, Date endDate) {
return selectedDate.after(startDate) && (selectedDate.before(endDate) || DateUtils.isSameDay(selectedDate, endDate));
}
public static boolean isWithinRange2Dates(Date selectedStartDate, Date selectedEndDate, Date startDate, Date endDate) {
return isWithinRange(selectedStartDate, startDate, endDate) && isWithinRange(selectedEndDate, startDate, endDate);
}
#SuppressLint("SimpleDateFormat")
public static Date string2Date(String dateStr) {
try {
return new SimpleDateFormat("dd/MM/yyyy").parse(dateStr);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
Issue:
28/09 --> 30/09 is within the 24/09 --> 30/09 so the method should true
Question:
How I can check if a selected start and end date are within a date range or not?
tl;dr
org.threeten.extra.LocalDateRange.of
(
LocalDate.of( … ) ,
LocalDate.of( … )
)
.encloses
(
LocalDateRange.of
(
startJavaSqlDate.toLocalDate() ,
stopJavaSqlDate.toLocalDate()
)
)
Avoid legacy date-time classes
You are using terrible date-time classes that were years ago supplanted by the modern java.time classes defined in JSR 310.
One of the many design flaws in the Date class is that there are actually two Date classes:
java.util.Date
java.sql.Date
The first represents a moment as seen in UTC. The second pretends to represent a date-only, without a time-of-day and without an offset or time zone. But actually, in a case of extremely poor judgement, the second class extends from the first… so it does indeed internally represent a moment in UTC. Messy? Yes, a terrible mess.
LocalDate
You neglect to mention in your Question which class you are using. So I'll go with the second one, java.sql.Date.
When handed a java.sql.Date object, immediately convert to the modern replacement: LocalDate. Do so by calling the new conversion method added to the old class.
LocalDate ld = myJavaSqlDate.toLocalDate() ;
LocalDateRange
To compare date ranges, you could write the code yourself. But why bother? Add the ThreeTen-Extra library to your project. Doing so gives you access to the LocalDateRange class. That class provides several handy methods such as contains, abuts, encloses, overlaps, etc.
LocalDateRange target =
LocalDateRange.of(
LocalDate.of( … ) ,
LocalDate.of( … )
)
;
… and:
LocalDateRange selected =
LocalDateRange.of(
startJavaSqlDate.toLocalDate() ,
stopJavaSqlDate.toLocalDate()
)
;
Compare.
boolean enclosed = target.encloses( selected ) ;
Your isWithin range functions operator
Precedence is wrong.Also checking isSameDate for both end and start dates are missing. In your code it return false if user startDate is simmilar to your dateRange start date or if user end date simmilar to datarange end date. Correct implementation as follows of isWithinRange function.
return (selectedDate.after(startDate) || DateUtils.isSameDay(selectedDate, startDate)) && (selectedDate.before(endDate) || DateUtils.isSameDay(selectedDate, endDate));
Use || operator not && for isWithinRange2Dates function as follows.
return isWithinRange(selectedStartDate, startDate, endDate) || isWithinRange(selectedEndDate, startDate, endDate);
try {
String hql = "SELECT taskDate FROM TaskFutureDates t WHERE t.taskId= : taskId";
List<java.sql.Date> result = em.createQuery(hql).setParameter("taskId", taskId).getResultList();
java.sql.Date currentDate =new Date(new java.util.Date().getTime());
if (result.size() != 0) {
for(java.sql.Date date: result) {
if(date.compareTo(currentDate)>=0) {
System.err.println("CAST= "+(Date) date);
return (java.sql.Date) date;
}
}
}
} catch (Exception e) {
// TODO: handle exception
//System.err.println(e);
}
return null;
}
when I am comparing the two dates I am getting error scenarios
1.when I am comparing alternative days I am getting -1
eg
09/04/2020
10/04/2020
when the date is same I am getting -1
eg
10/04/2020
10/04/2020
in the 2nd scenario, I should get 0 why the result is -1?
from the compareTo doc:
a value less than 0 if this Date is before the Date argument
today() (= last midnight) or probably any date from your table is less than now() (which includes the current time)
tl;dr
Use modern java.time classes to retrieve and compare stored date values against today’s date.
myResultSet.getObject( … , LocalDate.class ).isAfter( LocalDate.now( "Africa/Tunis" ) )
Details
As the correct Answer by Rotteveel explained, you should not be using the terrible class java.sql.Date. That class was years ago supplanted by the modern java.time classes. Specifically, java.time.LocalDate.
As of JDBC 4.2, we can exchange java.time objects with the database. For columns of a type akin to the standard-SQL type DATE, use setObject, updateObject, and getObject to exchange LocalDate objects.
LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;
To get today’s date requires a time zone. For any given moment, the date varies around the globe by time zone. So while it may be “tomorrow” in Tokyo Japan, it may simultaneously be “yesterday” in Toledo Ohio US.
If you do not specify a time zone, the JVM’s current default time zone is applied implicitly.
ZoneId z = ZoneId.of( "Asia/Tokyo" ) ;
LocalDate today = LocalDate.now( z ) ;
Compare using isEqual, isBefore, and isAfter methods.
Boolean isFuture = ld.isAfter( today ) ;
Although java.sql.Date is supposed to be a date, it actually is still a thin wrapper around epoch milliseconds. It doesn't truncate them. So two java.sql.Date values that are the same date, can still have two different epoch milliseconds values (ie check the getTime() result), and as a result they won't compare identical.
The implementation of the java.sql.Date constructor (Date(long)) is:
public Date(long date) {
// If the millisecond date value contains time info, mask it out.
super(date);
}
Contrary to the comment, nothing is masked out. This is probably because java.sql.Date is sensitive to the default JVM time zone, and trying to mask it out would only complicate things.
In any case, since Java 8 / JDBC 4.2, it would be better to use java.time.LocalDate instead of java.sql.Date.
If you can't fully switch to using LocalDate, I would recommend at least using:
LocalDate currentDate = LocalDate.now();
//...
if (date.toLocalDate().compareTo(currentDate) >= 0) {
// ...
}
Or - as shown in the answer by Basil Bourque - use the specialized comparison methods like isAfter, isBefore and isEqual.
I am storing current date in SQLite DB as
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
When I try to compare Calendar objects, its always shows objects as not equal.
Here is my code.
Creating Calendar from Database string
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Calendar calendarDB = Calendar.getInstance();
String date = "extracted only date (2014-03-03 for ex) from DB value ignoring time";
calendarDB.setTime(sdf.parse(date));
Current Calendar instance
Calendar calendarCurrent = Calendar.getInstance();
Comparison... I see not equal for all the instances.
if(calendarDB.equals(calendarCurrent))
Log.i(TAG, "equal!!!");
else
Log.i(TAG, "Not equal!!!");
I can see both Calendar instance values like day, month, year equal in Log.
What's wrong with it?
Calendar.getInstance() is not singleton. It every time creates a new instance of different implementations of java.util.Calendar based on Locale
Secondly, if you check equals method of Calendar, it checks lot more, than just the date
public boolean equals(Object obj) {
if (this == obj)
return true;
try {
Calendar that = (Calendar)obj;
return compareTo(getMillisOf(that)) == 0 &&
lenient == that.lenient &&
firstDayOfWeek == that.firstDayOfWeek &&
minimalDaysInFirstWeek == that.minimalDaysInFirstWeek &&
zone.equals(that.zone);
} catch (Exception e) {
// Note: GregorianCalendar.computeTime throws
// IllegalArgumentException if the ERA value is invalid
// even it's in lenient mode.
}
return false;
}
If you want to compare 2 dates then, you can do
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date one = new Date(); // one = calOne.getTime();
Date two = new Date(); //two = calTwo.getTime();
sdf.format(one).equals(sdf.format(two));
That's happens because a Calendar equals method compare to next fields :
#Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (!(object instanceof Calendar)) {
return false;
}
Calendar cal = (Calendar) object;
return getTimeInMillis() == cal.getTimeInMillis()
&& isLenient() == cal.isLenient()
&& getFirstDayOfWeek() == cal.getFirstDayOfWeek()
&& getMinimalDaysInFirstWeek() == cal.getMinimalDaysInFirstWeek()
&& getTimeZone().equals(cal.getTimeZone());
}
So you need to check :
millis
isLenient
first day of week
minimal days in first week
and time zone
As you can see equals method need a same TimeZone in comaprable object.
tl;dr
LocalDate.now( ZoneId( "Pacific/Auckland" ) ) // Get today’s date in a particular time zone.
.isEqual( // Test for equality against a `LocalDate` object to be retrieved from database.
myResultSet.getObject( … , Instant.class ) // Retrieve a moment in UTC from the database, an `Instant` object.
.atZone( ZoneId( "Pacific/Auckland" ) ) // Produce a `ZonedDateTime` to represent the same moment in time but with the wall-clock time of a particular region’s time zone.
.toLocalDate() // Extract a date-only value, without time-of-day and without time zone.
)
java.time
The modern approach uses the java.time classes.
With JDBC 4.2 and later, you may directly exchange java.time objects with your database. No need for the troublesome Calendar class, no need for mere strings.
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).
Instant instant = myResultSet.getObject( … , Instant.class ) ;
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
Apply the ZoneId to your Instant to get a ZonedDateTime.
ZonedDateTime zdt = instant.atZone( z ) ;
If you care about only the date portion, and not the time-of-day, extract a LocalDate.
LocalDate ld = zdt.toLocalDate() ;
Compare to the current date.
LocalDate today = LocalDate.now( z ) ;
Boolean isSameDateAsToday = ld.isEqual( today ) ;
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….
I am sure this was done 1000 times in 1000 different places. The question is I want to know if there is a better/standard/faster way to check if current "time" is between two time values given in hh:mm:ss format. For example, my big business logic should not run between 18:00:00 and 18:30:00. So here is what I had in mind:
public static boolean isCurrentTimeBetween(String starthhmmss, String endhhmmss) throws ParseException{
DateFormat hhmmssFormat = new SimpleDateFormat("yyyyMMddhh:mm:ss");
Date now = new Date();
String yyyMMdd = hhmmssFormat.format(now).substring(0, 8);
return(hhmmssFormat.parse(yyyMMdd+starthhmmss).before(now) &&
hhmmssFormat.parse(yyyMMdd+endhhmmss).after(now));
}
Example test case:
String doNotRunBetween="18:00:00,18:30:00";//read from props file
String[] hhmmss = downTime.split(",");
if(isCurrentTimeBetween(hhmmss[0], hhmmss[1])){
System.out.println("NOT OK TO RUN");
}else{
System.out.println("OK TO RUN");
}
What I am looking for is code that is better
in performance
in looks
in correctness
What I am not looking for
third-party libraries
Exception handling debate
variable naming conventions
method modifier issues
this is all you should need to do, this method is loosely coupled from the input and highly coherent.
boolean isNowBetweenDateTime(final Date s, final Date e)
{
final Date now = new Date();
return now.after(s) && now.before(e);
}
how you get the Date objects for start and end is irrelevant to comparing them. You are making things way more complicated than you need to with passing String representations around.
Here is a better way to get the start and end dates, again loosely coupled and highly coherent.
private Date dateFromHourMinSec(final String hhmmss)
{
if (hhmmss.matches("^[0-2][0-9]:[0-5][0-9]:[0-5][0-9]$"))
{
final String[] hms = hhmmss.split(":");
final GregorianCalendar gc = new GregorianCalendar();
gc.set(Calendar.HOUR_OF_DAY, Integer.parseInt(hms[0]));
gc.set(Calendar.MINUTE, Integer.parseInt(hms[1]));
gc.set(Calendar.SECOND, Integer.parseInt(hms[2]));
gc.set(Calendar.MILLISECOND, 0);
return gc.getTime();
}
else
{
throw new IllegalArgumentException(hhmmss + " is not a valid time, expecting HH:MM:SS format");
}
}
Now you can make two well named method calls that will be pretty self documenting.
tl;dr
LocalTime now =
ZonedDateTime
.now( ZoneId.of( "America/Montreal" ) )
.toLocalTime() ;
Boolean isBetween =
( ! now.isBefore( LocalTime.of( 18 , 0 ) ) // "not before" means "is equal to OR after".
&&
now.isBefore( LocalTime.of( 18 , 30 ) ) ; // Half-Open, beginning is *inclusive* while ending is *exclusive*.
Using java.time
You are using old date-time classes that have proven to be poorly designed, confusing, and troublesome. They are now legacy, supplanted by the java.time classes.
LocalTime
Do not pass mere strings representing time-of-day values. We now have a type for that, the LocalTime class.
LocalTime start = LocalTime.of( 18 , 0 );
LocalTime stop = LocalTime.of( 18 , 30 );
Pass those instances to your utility method. That method should not have to do any parsing, so no need to throw the parsing exception.
public static boolean isCurrentTimeBetween( LocalTime start , LocalTime stop ) {
…
ZonedDateTime
A time zone is crucial in determining the current date and time-of-day. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.now( z );
To compare the time-of-day of now, we could simply extract a LocalTime from that ZonedDateTime. But we have the problem of anomalies, such as Daylight Saving Time (DST) and politicians redefining time zones. There may not be any 6 PM hour on a particular date. The solution to this conundrum depends on your business context and your business rules. You could either ignore the conundrum and stick with literally asking if the current time is between your target start-stop time. Or you could apply the time zone to your start-stop times-of-day of day and let ZonedDateTime class make adjustments as it sees fit. Let's look at both approaches.
Ignore anomalies
First, ignore any anomalies. Ask simply and literally if the current time-of-day is between the target start and stop times-of-day.
We can extract a time-of-day object from the zoned date-time object.
LocalTime localTimeNow = zdt.toLocalTime(); // Extract a time-of-day from the zoned date-time object.
Compare that to our stop-start times-of-day. Note that we use here the Half-Open approach to defining a span of time. In this approach the beginning is inclusive while the ending is exclusive. This approach is common in date-time work and generally is the wise way to go.
Boolean isNowOnOrAfterStart = ( ! localTimeNow.isBefore( start ) ) ; // A briefer way of asking "is equal to OR is after" is "is not before".
Boolean isNowBeforeStop = localTimeNow.isBefore( stop );
Boolean isNowInTargetZone = ( isNowOnOrAfterStart && isNowBeforeStop ); // Half-Open: beginning is inclusive while ending is exclusive.
Consider anomalies
Next we consider any anomalies. We apply the start and stop times-of-day to the current date within the same time zone. We extract the date-only from the zoned date-time object.
LocalDate localDateToday = zdt.toLocalDate();
ZonedDateTime zdtStart = ZonedDateTime.of( localDateToday , start , z );
ZonedDateTime zdtStop = ZonedDateTime.of( localDateToday , stop , z );
Study the class documentation to understand the behavior of ZonedDateTime.of in resolving invalid time-of-day values. There is no perfect way to resolve nonexistent time-of-day values, so you must decide if this class’ way meets your business rules.
ZonedDateTime.of
public static ZonedDateTime of(LocalDate date, LocalTime time, ZoneId zone)
Obtains an instance of ZonedDateTime from a local date and time.
This creates a zoned date-time matching the input local date and time as closely as possible. Time-zone rules, such as daylight savings, mean that not every local date-time is valid for the specified zone, thus the local date-time may be adjusted.
The local date time and first combined to form a local date-time. The local date-time is then resolved to a single instant on the time-line. This is achieved by finding a valid offset from UTC/Greenwich for the local date-time as defined by the rules of the zone ID.
In most cases, there is only one valid offset for a local date-time. In the case of an overlap, when clocks are set back, there are two valid offsets. This method uses the earlier offset typically corresponding to "summer".
In the case of a gap, when clocks jump forward, there is no valid offset. Instead, the local date-time is adjusted to be later by the length of the gap. For a typical one hour daylight savings change, the local date-time will be moved one hour later into the offset typically corresponding to "summer".
Apply the same comparison logic as we saw above.
Boolean isNowOnOrAfterStart = ( ! zdt.isBefore( zdtStart ) ) ; // A briefer way of asking "is equal to OR is after" is "is not before".
Boolean isNowBeforeStop = zdt.isBefore( zdtStop );
Boolean isNowInTargetZone = ( isNowOnOrAfterStart && isNowBeforeStop ); // Half-Open: beginning is inclusive while ending is exclusive.
Alternative way to make the comparison is to use the handy Interval class from the ThreeTen-Extra project. That class takes a pain of Instant objects, which you can extract from your ZonedDateTime objects. 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).
Interval interval = Interval.of( zdtStart.toInstant() , zdtStop.toInstant() );
Boolean isNowInTargetZone = interval.contains( zdt.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.
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 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.
As pointed out by Kevin, Fuzzy Lollipop's Regex won't pick up times between 14:00 and 19:00.
To get match a full 24 hour clock, you can use this:
if (hhmmss.matches("^([0-1][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$"))
{
// Do stuff here
}
The following Class is something I just created out of some of the code from other answers. It encapsulates the behavior of a 'time period' without relating to specific days. Our system is using this Class to check if the current time is within one of our designated maintenance windows. i.e. 05:00:00 - 07:00:00
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
/**
*
* #author Adam Yocum
*/
public class ExclusionTimePeriod {
private String timeStart;
private String timeEnd;
/**
* #return the timeStart
*/
public String getTimeStart() {
return timeStart;
}
/**
* #param timeStart the timeStart to set
*/
public void setTimeStart(String timeStart) {
if (timeStart.matches("^([0-1][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$"))
{
this.timeStart = timeStart;
}
else
{
throw new IllegalArgumentException(timeStart + " is not a valid time, expecting HH:MM:SS format");
}
}
/**
* #return the timeEnd
*/
public String getTimeEnd() {
return timeEnd;
}
/**
* #param timeEnd the timeEnd to set
*/
public void setTimeEnd(String timeEnd) {
if (timeEnd.matches("^([0-1][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$"))
{
this.timeEnd = timeEnd;
}
else
{
throw new IllegalArgumentException(timeEnd + " is not a valid time, expecting HH:MM:SS format");
}
}
private Date toDate(String hhmmss){
final String[] hms = hhmmss.split(":");
final GregorianCalendar gc = new GregorianCalendar();
gc.set(Calendar.HOUR_OF_DAY, Integer.parseInt(hms[0]));
gc.set(Calendar.MINUTE, Integer.parseInt(hms[1]));
gc.set(Calendar.SECOND, Integer.parseInt(hms[2]));
gc.set(Calendar.MILLISECOND, 0);
Date date = gc.getTime();
return date;
}
public boolean isNowInPeriod()
{
final Date now = new Date();
return now.after(toDate(getTimeStart())) && now.before(toDate(getTimeEnd()));
}
public static void main(String[] args){
//Test All possible hours
for(int hour=0;hour<=23;hour++){
String hourStr = "";
if(hour<=9){
hourStr = "0"+hour;
}else{
hourStr = ""+hour;
}
for(int min=0;min<60;min++){
String minStr = "";
if(min<=9){
minStr = "0"+min;
}else{
minStr = ""+min;
}
for(int sec=0;sec<60;sec++){
String secStr = "";
if(sec<=9){
secStr = "0"+sec;
}else{
secStr = ""+sec;
}
String hhmmss = hourStr+":"+minStr+":"+secStr;
ExclusionTimePeriod period = new ExclusionTimePeriod();
period.setTimeStart(hhmmss);
period.setTimeEnd(hhmmss);
System.out.println(hhmmss+" Ok");
}
}
}
//Test isInPeriod functionality
ExclusionTimePeriod isInTest = new ExclusionTimePeriod();
isInTest.setTimeStart("10:00:00");
isInTest.setTimeEnd("10:43:00");
System.out.println((new Date())+" is between "+isInTest.getTimeStart()+" and "+isInTest.getTimeEnd()+" = "+isInTest.isNowInPeriod());
}
}
The Midnight Problem
Other answers fail to mention it - and the OP doesn't ask - but you should really consider when the interval spans across midnight.
Time is difficult. I purposely left the "long" version of the code and didn't abbreviate logical conditions to make it as clear as possible the what's and the why's.
/**
* Takes into consideration that the interval may span accross midnight
*
* #param clock to make unit testing easier, just replace for Clock.systemUTC() in your code
* #param start the interval start
* #param end the interval end
* #return true if "now" is inside the specified interval
*/
static boolean isNowBetweenLocalTime(Clock clock, final LocalTime start, final LocalTime end) {
LocalTime now = LocalTime.now(clock);
// if interval crosses midnight
if (end.isBefore(start)) {
if (now.isAfter(start) && now.isAfter(end)) {
return true;
}
if (now.isBefore(start) && now.isBefore(end)) {
return true;
}
return false;
}
// if interval does not cross midnight
if (end.isAfter(start)) {
if (now.isAfter(start) && now.isBefore(end)) {
return true;
}
return false;
}
return false; // interval is 0 so start and end always outside interval
}
Verbosity is not always wrong. This method will be buried in a utility class and two years from now you'll thank yourself for understanding what it does!
The dateFromHourMinSec method is flawed as written. It won't allow any hours where the seconde digit is greater than 3, e.g. 18:00:00. If you change it to allow [0-2][0-9] it will allow times such as 29:00:00.
Have a fix for that?
I need to determine the current year in Java as an integer. I could just use java.util.Date(), but it is deprecated.
For Java 8 onwards:
int year = Year.now().getValue();
For older version of Java:
int year = Calendar.getInstance().get(Calendar.YEAR);
Using Java 8's time API (assuming you are happy to get the year in your system's default time zone), you could use the Year::now method:
int year = Year.now().getValue();
This simplest (using Calendar, sorry) is:
int year = Calendar.getInstance().get(Calendar.YEAR);
There is also the new Date and Time API JSR, as well as Joda Time
You can also use 2 methods from java.time.YearMonth( Since Java 8 ):
import java.time.YearMonth;
...
int year = YearMonth.now().getYear();
int month = YearMonth.now().getMonthValue();
tl;dr
ZonedDateTime.now( ZoneId.of( "Africa/Casablanca" ) )
.getYear()
Time Zone
The answer by Raffi Khatchadourian wisely shows how to use the new java.time package in Java 8. But that answer fails to address the critical issue of time zone in determining a date.
int year = LocalDate.now().getYear();
That code depends on the JVM's current default time zone. The default zone is used in determining what today’s date is. Remember, for example, that in the moment after midnight in Paris the date in Montréal is still 'yesterday'.
So your results may vary by what machine it runs on, a user/admin changing the host OS time zone, or any Java code at any moment changing the JVM's current default. Better to specify the time zone.
By the way, always use proper time zone names as defined by the IANA. Never use the 3-4 letter codes that are neither standardized nor unique.
java.time
Example in java.time of Java 8.
int year = ZonedDateTime.now( ZoneId.of( "Africa/Casablanca" ) ).getYear() ;
Joda-Time
Some idea as above, but using the Joda-Time 2.7 library.
int year = DateTime.now( DateTimeZone.forID( "Africa/Casablanca" ) ).getYear() ;
Incrementing/Decrementing Year
If your goal is to jump a year at a time, no need to extract the year number. Both Joda-Time and java.time have methods for adding/subtracting a year at a time. And those methods are smart, handling Daylight Saving Time and other anomalies.
Example in java.time.
ZonedDateTime zdt =
ZonedDateTime
.now( ZoneId.of( "Africa/Casablanca" ) )
.minusYears( 1 )
;
Example in Joda-Time 2.7.
DateTime oneYearAgo = DateTime.now( DateTimeZone.forID( "Africa/Casablanca" ) ).minusYears( 1 ) ;
The easiest way is to get the year from Calendar.
// year is stored as a static member
int year = Calendar.getInstance().get(Calendar.YEAR);
If you want the year of any date object, I used the following method:
public static int getYearFromDate(Date date) {
int result = -1;
if (date != null) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
result = cal.get(Calendar.YEAR);
}
return result;
}
Use the following code for java 8 :
LocalDate localDate = LocalDate.now();
int year = localDate.getYear();
int month = localDate.getMonthValue();
int date = localDate.getDayOfMonth();
You can also use Java 8's LocalDate:
import java.time.LocalDate;
//...
int year = LocalDate.now().getYear();
If your application is making heavy use of Date and Calendar objects, you really should use Joda Time, because java.util.Date is mutable. java.util.Calendar has performance problems when its fields get updated, and is clunky for datetime arithmetic.
As some people answered above:
If you want to use the variable later, better use:
int year;
year = Calendar.getInstance().get(Calendar.YEAR);
If you need the year for just a condition you better use:
Calendar.getInstance().get(Calendar.YEAR)
For example using it in a do while that checks introduced year is not less than the current year-200 or more than the current year (Could be birth year):
import java.util.Calendar;
import java.util.Scanner;
public static void main (String[] args){
Scanner scannernumber = new Scanner(System.in);
int year;
/*Checks that the year is not higher than the current year, and not less than the current year - 200 years.*/
do{
System.out.print("Year (Between "+((Calendar.getInstance().get(Calendar.YEAR))-200)+" and "+Calendar.getInstance().get(Calendar.YEAR)+") : ");
year = scannernumber.nextInt();
}while(year < ((Calendar.getInstance().get(Calendar.YEAR))-200) || year > Calendar.getInstance().get(Calendar.YEAR));
}
In my case none of the above is worked. So After trying lot of solutions i found below one and it worked for me
import java.util.Scanner;
import java.util.Date;
public class Practice
{
public static void main(String[] args)
{
Date d=new Date();
int year=d.getYear();
int currentYear=year+1900;
System.out.println(currentYear);
}
}
I may add that a simple way to get the current year as an integer is importing
java.time.LocalDate and, then:
import java.time.LocalDate;
int yourVariable = LocalDate.now().getYear()
Hope this helps!
You can do the whole thing using Integer math without needing to instantiate a calendar:
return (System.currentTimeMillis()/1000/3600/24/365.25 +1970);
May be off for an hour or two at new year but I don't get the impression that is an issue?
In Java version 8+ can (advised to) use java.time library. ISO 8601 sets standard way to write dates: YYYY-MM-DD and java.time.Instant uses it, so (for UTC):
import java.time.Instant;
int myYear = Integer.parseInt(Instant.now().toString().substring(0,4));
P.S. just in case (and shorted for getting String, not int), using Calendar looks better and can be made zone-aware.
I use special functions in my library to work with days/month/year ints -
int[] int_dmy( long timestamp ) // remember month is [0..11] !!!
{
Calendar cal = new GregorianCalendar(); cal.setTimeInMillis( timestamp );
return new int[] {
cal.get( Calendar.DATE ), cal.get( Calendar.MONTH ), cal.get( Calendar.YEAR )
};
};
int[] int_dmy( Date d ) {
...
}