In Java (I'm a junior) - how do you perform various date operations?
Assess "storedDate is one week away from today" and "storedDate has passed"
I am not sure if its the best approach or how to do the condition check
java.sql.Date dueDate = (Date) loggedUser.get("dueDate");
I've seen various calculations like this - but not sure an if condition could be met like this?
Calendar c= Calendar.getInstance();
//c.set(Calendar.DAY_OF_WEEK,Calendar.SUNDAY);
c.set(Calendar.HOUR_OF_DAY,0);
c.set(Calendar.MINUTE,0);
c.set(Calendar.SECOND,0);
DateFormat df=new SimpleDateFormat("EEE yyyy/MM/dd HH:mm:ss");
System.out.println(df.format(c.getTime()));// This past Sunday [ May include today ]
c.add(Calendar.DATE,7);
System.out.println(df.format(c.getTime()));// Next Sunday
Step 1: Learn to read API pages.
Here is the Calendar API Page, read it.
For your class project, you don't care about timezone (since you didn't mention it in your post).
Get a date parameter: public void methodName(Date dateParameter)
Create a Calendar containing now: Calendar myCalendar = Calendar.getInstance();
Set a calendar to a date value: myCalendar.setTime(dateParameter)
"Calculate" one week from today: myCalendar.roll(Calendar.DAY_OF_YEAR, 7)
The Calendar object stores Millisecond, Second, Minute, and Hour.
Clear these using the set method.
Compare Calendar objects using the after method.
tl;dr
LocalDate.now( ZoneId.of( "Pacific/Auckland" ) )
.with(
TemporalAdjusters.previousOrSame( DayOfWeek.SUNDAY )
)
java.time
The modern approach uses java.time classes.
Get current moment in UTC.
Instant instant = Instant.now() ;
If you care about day-of-week, you care about date. Determining a date requires a time zone. For any given moment the date varies around the globe by zone.
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = instant.atZone( z ) ; // Same point on the timeline, different wall-clock time.
To focus on date-only without time-of-day, extract a LocalDate.
LocalDate ld = zdt.toLocalDate() ;
To adjust into other moments, use a TemporalAdjuster. Find implementations in TemporalAdjusters.
LocalDate previousOrSameSunday = ld.with(
TemporalAdjusters.previousOrSame( DayOfWeek.SUNDAY )
) ;
…and…
LocalDate nextOrSameSunday = ld.with(
TemporalAdjusters.nextOrSame( DayOfWeek.SUNDAY )
) ;
To compare, look for isBefore, isAfter, isEqual, and equals methods on the various java.time classes.
thisLocalDate.isBefore( thatLocalDate)
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
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.
Related
I have the below declaration in java class
abc.setCreated(abcEntity.getCreatedDate());
and if I go deep inside the call inside abc entity
public Date getCreatedDate() {
return new Date(createdDate.getTime());
}
but the date in the outcome of
abc.setCreated(abcEntity.getCreatedDate());
shown as in request "created": 15704064000 and I want it to be shown as the date in DD-MM-YYYY format please advise how to achieve this
You can use SimpleDateFormat in java to get the date in that format. Instead of the time, pass the Date object like bellow.
ex:-
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd-MM-yyyy");
String formattedDate = simpleDateFormat.format(new Date());
System.out.println(formattedDate);
tl;dr
Instant.
.ofEpochSecond(
1_570_406_400L
)
.atOffset(
ZoneOffset.UTC
)
.format(
DateTimeFormatter.ofPattern( "dd-MM-uuuu" )
)
07-10-2019
Avoid legacy classes
You are using terrible date-time classes that were supplanted years ago by the modern java.time classes.
java.time
Parse your count of whole seconds since the epoch reference of first moment of 1970 in UTC as a Instant.
Is your example value correct? Perhaps you meant 1,570,406,400.
long seconds = 1_570_406_400L ;
Instant instant = Instant.ofEpochMilli( seconds ) ;
The Instant represents a moment in UTC. Generate a string representing this value in standard ISO 8601 format.
String output = instant.toString() ;
instant.toString(): 2019-10-07T00:00:00Z
To adjust to another time zone, apply a ZoneId to get a ZonedDateTime.
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
zdt.toString(): 2019-10-06T20:00-04:00[America/Montreal]
Notice how the date is the 6th rather than the 7th. While at that moment a new day has begun in UTC, it is still “yesterday” in Canada. For any given moment, the date varies around the globe by time zone.
Generate a string a localized format.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd-MM-uuuu" );
String output = zdt.format( f ) ;
output: 06-10-2019
If you want to report the date as seen in UTC rather than a time zone, use OffsetDateTime class. Specify UTC using the constant ZoneOffset.UTC.
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd-MM-uuuu" );
String output = odt.format( f ) ;
outputOdt: 07-10-2019
See all that code run live at IdeOne.com.
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.
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 adds 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 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.
how to mock following code? i dont want to change my code.
Date date = new Date();
String res_timestamp=new Timestamp(date.getTime()).toString();
my code:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("PST"));
Date NOW = sdf.parse("2019-02-11 00:00:00");
Timestamp time=new Timestamp(NOW.getTime());
whenNew(Timestamp.class).withNoArguments().thenReturn(time);
how can i mock it? am finding hard to mock it.
how can i solve it?
note: i do not want to change my code. without changing my code i have to mock those two lines.
tl;dr
Use java.time.Clock, ZonedDateTime, Instant, ZoneId.
Inject an altered Clock object as a dependency: Clock.fixed( … ).
Never use Date, Calendar, SimpleDateFormat, Timestamp, TimeZone.
Pass an altered Clock object as a dependency
You are using terrible date-time classes that were supplanted years ago by the java.time classes defined by JSR 310.
The java.time.Clock class offers several alternate behaviors suitable for testing. These included a fixed point in time, altered cadences, and and adjustment from the current moment.
Pass one of these Clock objects to the various methods in the java.time classes for your testing purposes.
PST is not a time zone. Specify a proper time zone name in the format of Continent/Region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-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/Los_Angeles" ) ;
Build up the specific moment you have in mind for your testing.
LocalDate ld = LocalDate.of( 2019 , 2 , 11 ) ;
LocalTime lt = LocalTime.MIN ;
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;
zdt.toString(): 2019-02-11T00:00-08:00[America/Los_Angeles]
Calling Clock.fixed requires an Instant, a moment in UTC. We can adjust from our zoned value to UTC by extracting an Instant. Same moment, same point on the timeline, different wall-clock time.
Instant instant = zdt.toInstant() ;
instant.toString(): 2019-02-11T08:00:00Z
Specify a Clock that forever reports the current moment as that specific moment, without incrementing.
Clock clock = Clock.fixed( instant , z ) ;
clock.toString(): FixedClock[2019-02-11T08:00:00Z,America/Los_Angeles]
Inject the fixed clock as a dependency.
Instant now = Instant.now( clock ) ; // Tell me a lie.
now.toString(): 2019-02-11T08:00:00Z
See this code run live at IdeOne.com.
JDBC 4.2
If you were instantiating java.sql.Timestamp for use with a database, instead use the java.time classes. As of JDBC 4.2, we can exchange java.time objects with a database.
Your JDBC driver might have optional support for Instant.
myPreparedStatement.setObject( … , instant ) ; // Storing data.
Instant instant = myResultSet.get( … , Instant.class ) ; // Retrieving data.
Your driver must support OffsetDateTime.
myPreparedStatement.setObject( … , instant.atOffset( ZoneOffset.UTC ) ) ; // Storing data.
OffsetDateTime odt = myResultSet.get( … , OffsetDateTime.class ) ; // Retrieving data.
Adjust into a time zone.
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;
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, Java SE 11, and later - 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
Most 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.
I am trying to save a date in DB but i am getting the below error. I am confused because i am sending the same format but still throwing exception:
java.lang.IllegalArgumentException: Timestamp format must be
yyyy-mm-dd hh:mm:ss[.fffffffff]
If i am trying in SQL Developer in the below way it works fine
to_date('01/01/1900', 'mm/dd/yyyy')
Through java i tried doing as below
First Method
SimpleDateFormat format1 = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
Date myDate = format1.parse("01/01/1900 00:00:00");
Second Method
SimpleDateFormat format1 = new SimpleDateFormat("dd/MM/yyyy");
Date myDate = format1.parse("01/01/1900");
Where am i going wrong.
P.S : Please before marking it as duplicate and stopping people from answering question understand i have tried something and got the error.
tl;dr
myPreparedStatement.setObject(
… ,
LocalDate.parse(
"01/01/1900" ,
DateTimeFormatter.ofPattern( "dd/MM/uuuu" )
)
)
Details
The Answer by Just another Java programmer is correct.
Furthermore, you should not use strings to communicate date-time values with a database. Use date-time classes.
The modern way is with java.time classes, supplanting the troublesome legacy date-time classes.
LocalDate
The LocalDate class represents a date-only value without time-of-day and without time zone.
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.
ZoneId z = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( z );
You can parse directly from a string in standard ISO 8601 format.
LocalDate localDate = LocalDate.parse( "2016-01-23" );
Or specify each part.
LocalDate localDate = LocalDate.of( 2016, Month.JANUARY , 23 );
To parse other formats, use DateTimeFormatter class. Search Stack Overflow for many examples.
Database
If your JDBC driver complies with JDBC 4.2 or later, it should be able to pass a java.time type with PreparedStatement::setObject and fetch with ResultSet::getObject.
myPreparedStatement.setObject( … , localDate );
…or…
myPreparedStatement.setObject( … , localDate , JDBCType.DATE );
If your driver is not so enabled, fall back to using java.sql.Date. This awkward class pretends to represent a date-only value (but actually has a time component set to midnight which we are supposed to ignore). To convert to/from java.time look to new methods added to the old classes.
java.sql.Date sqlDate = java.sql.Date.valueOf( localDate );
And going the other direction.
LocalDate localDate = sqlDate.toLocalDate();
Pass to PreparedStatement::setDate.
myPreparedStatement.setDate( … , sqlDate );
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 java.time.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8 and SE 9 and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
Your date pattern does not match.
Better is to use a PreparedStatement so you never will rely on string conversion.
My class has 2 properties that make up its date:
java.util.Date date;
String timeZone;
How can I see if this date is before the current time on the server?
Basically I want to write something like this, but take timeZone into account:
return date.before(new Date());
Date stores internally as UTC, so your timeZone variable is not necessary. You can simply use Date.before(Date).
Calendar startCalendar = Calendar.getInstance();
int startTimeZoneOffset = TimeZone.getTimeZone(timeZone).getOffset(startDate.getTime()) / 1000 / 60;
startCalendar.setTime(startDate);
startCalendar.add(Calendar.MINUTE, startTimeZoneOffset);
Calendar nowCalendar = Calendar.getInstance();
int nowTimeZoneOffset = nowCalendar.getTimeZone().getOffset(new Date().getTime()) / 1000 / 60;
nowCalendar.setTime(new Date());
nowCalendar.add(Calendar.MINUTE, nowTimeZoneOffset);
return startCalendar.before(nowCalendar);
tl;dr
Use Instant class, which is always in UTC. So time zone becomes a non-issue.
someInstant.isBefore( Instant.now() )
java.time
The modern approach uses the java.time classes that supplanted the terrible Date & Calendar classes.
As the correct Answer by Kuo stated, your java.util.Date is recording a moment in UTC. So no need for a time zone.
Likewise, its replacement, the java.time.Instant class, also records a moment in UTC. So no time zone needed.
Instant instant = Instant.now() ; // Capture current in UTC.
So all you need as member variables on your class is Instant.
public class Event {
Instant when ;
…
}
To compare Instant objects, use the isAfter, isBefore, and equals methods.
someInstant.isBefore( Instant.now() )
For presentation in a time zone expected by the user, assign a ZoneId to get a ZonedDateTime object. The Instant and the ZonedDateTime both represent the same moment, the same point on the timeline, but viewed through different wall-clock time.
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z ) ; // Same moment, different wall-clock time.
String output = zdt.toString() ; // Generate text in standard ISO 8601 format, wisely extended to append the name of the zone in square brackets.
Or let java.time automatically localize output. To localize, specify:
FormatStyle to determine how long or abbreviated should the string be.
Locale to determine:
The human language for translation of name of day, name of month, and such.
The cultural norms deciding issues of abbreviation, capitalization, punctuation, separators, and such.
Example:
Locale l = Locale.CANADA_FRENCH ; // Or Locale.US, Locale.JAPAN, etc.
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL )
.withLocale( l );
String output = zdt.format( f );
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, Java SE 11, and later - 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
Most 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.
How to check whether the given date is earlier than a month ago? What is the fastest algorithm? I have to take into account that different months have different numbers of days.
Updated to Java 8
The class LocalDate class can be used:
LocalDate aDate = LocalDate.parse("2017-01-01");
return aDate.isBefore( LocalDate.now().minusMonths(1));
For previous versions, the Calendar class would work.
Calendar calendar = Calendar.getInstance();
calendar.add( Calendar.MONTH , -1 );
return aDate.compareTo( calendar.getTime() ) < 0;
Sample code:
import static java.lang.System.out;
import java.time.LocalDate;
public class Sample {
public static void main( String [] args ) {
LocalDate aMonthAgo = LocalDate.now().minusMonths(1);
out.println( LocalDate.parse("2009-12-16").isBefore(aMonthAgo));
out.println( LocalDate.now().isBefore(aMonthAgo));
out.println( LocalDate.parse("2017-12-24").isBefore(aMonthAgo));
}
}
Prints
true
false
false
Using Joda Time:
DateTime dt1 = new DateTime(); //Now
DateTime dt2 = new DateTime(2009,9,1,0,0,0,0); //Other date
if (dt1.plusMonths(-1) > dt2) {
//Date is earlier than a month ago
}
tl;dr
LocalDate.now( ZoneId.of( "America/Montreal" )
.minusMonths( 1 )
.isAfter( LocalDate.parse( "2017-01-23" ) )
java.time
The modern approach uses the java.time classes rather than the troublesome legacy classes such as Date & Calendar.
Today
First get the current date. The LocalDate class represents a date-only value without time-of-day and without time zone.
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" );
LocalDate today = LocalDate.now( z );
Calculating month-ago
Next, determine the date a month ago.
LocalDate monthAgo = today.minusMonths( 1 ) ;
Here are the rules used by LocalDate::minusMonths, quoted from Java 8 class doc:
This method subtracts the specified amount from the months field in three steps:
Subtract the input months from the month-of-year field
Check if the resulting date would be invalid
Adjust the day-of-month to the last valid day if necessary
For example, 2007-03-31 minus one month would result in the invalid date 2007-02-31. Instead of returning an invalid result, the last valid day of the month, 2007-02-28, is selected instead.
Or, perhaps in your business rules you meant "30 days" instead of a calendar month.
LocalDate thirtyDaysAgo = today.minusDays( 30 ) ;
Input
You are given a date. That should be passed to your code as a LocalDate object.
LocalDate ld = LocalDate.of( 2017 , Month.JANUARY , 23 ) ;
If coming from a String, use the standard ISO 8601 formats. For other formats, search Stack Overflow for DateTimeFormatter class.
LocalDate ld = LocalDate.parse( "2017-01-23" ) ;
Comparison
Now compare. Call the isBefore, isEqual, isAfter methods.
Boolean outdated = ld.isBefore( monthAgo ) ;
Performance
As for the issue of performance raised in the Question: Don't worry about it. This month-ago calculation and comparison is very unlikely to be a bottleneck in your app. Avoid premature optimization.
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
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.