I need to append 23 Hrs and 59 mins in the date using the Java calendar class.
e.g. 17/03/2022 - has java Date as a datatype - mapped to Date in Oracle
need to be stored in the database as 17/03/2022 23.59.00 - has Timestamp as data type.
I got the following function which works in most cases, but sometimes the date goes to the next day with the timestamp of 00.00.00 .
public Date addHoursToJavaUtilDate(Date date, int hours,int mins) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(Calendar.HOUR_OF_DAY, hours); //hours = 23
calendar.add(Calendar.MINUTE, mins); //mins = 59
return (Date) calendar.getTime();
}
Why does it works in most of the cases but not all the time? Will reducing the number of mins to 30 will help me?
Do you not have the chance to use java.time.* classes?
I know you specified Calendar usage, but notice how much simplicity you're missing: (written in Kotlin for easier readability)
val yourDate: LocalDateTime = ... // (or if you have TimeZone info, it would be `ZonedDateTime`)
val newDate = yourDate.plusHours(23).plusMinutes(59)
that's it.
You are using terrible date-time classes that were supplanted years ago by the modern java.time classes defined in JSR 310.
Calendar, actually GregorianCalendar, was replaced by ZonedDateTime.
Data and time
Capturing the current moment requires a time zone. For any given moment the date and the time can vary around the globe by time zone.
ZoneId z = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
You want to set the time of day to 23:59:00. We can produce a new ZonedDateTime object based on the old one but with a different time of day. Be aware that your specified time of day will be altered if not valid on that date in that zone, because of anomalies such as Daylight Saving Time (DST).
LocalTime lt = LocalTime.of( 23 , 59 ) ;
ZonedDateTime zdt2359 = zdt.with( lt ) ;
Alternatively, you could capture the current date only. Then assemble a ZonedDateTime from the three parts of date, time, and zone.
LocalDate ld = LocalDate.now ( z ) ;
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;
Database access
For database access, do not use legacy class Timestamp. Use OffsetDateTime to record a moment in SQL databases.
Write this value to a database column of a type akin to the SQL-standard type TIMESTAMP WITH TIME ZONE.
OffsetDateTime odt = zdt2359.toOffsetDateTime() ;
myPreparedStatement.setObject( … , odt ) ;
Retrieval.
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
Caveat: If you are trying to represent the end of a day, your 23:59 is the wrong approach. You are missing the last minute of the day. And some dates in some zones are not 24 hours long. Instead, learn about tracking time with Half-Open approach.
Related
I am using ZonedDateTime to convert GMT timestamp to America/Phoenix timestamp,
Here is my implementation
public static ZonedDateTime convertGMTTimestampToLocalTime(Timestamp gmtTime, String timeZone) throws Exception
{
ZonedDateTime atZone =Instant
.ofEpochMilli( // Parse a count of milliseconds since 1970-01-01T00:00Z.
gmtTime.getTime()
) // Returns a `Instant` object.
.atZone(
ZoneId.of( timeZone )
); // Returns a `ZonedDateTime` object.
return atZone;
}
This gives proper result when I test in local but when I test it remotely (server with docker container) it gives wrong result.
If I do a transaction at 6-Jan-2021 8:00PM (America/Phoenix) it should give 6-Jan-2021 instead it display 7-Jan-2021. My server is in MST
What am I missing, isn't the server supposed to print the date according to the specified time zone. Any help would be appreciated. Thanks.
Avoid legacy date-time classes
Never use the terrible legacy classes Timestamp, Date, Calendar, etc. These were years ago supplanted by the modern java.time classes defined in JSR 310.
Use java.time
If handed an object of that class, immediately convert to Instant. The Instant class represents a moment as seen in in UTC, with an offset of zero hours-minutes-seconds.
Instant instant = myTimestamp.toInstant() ;
Adjust to your desired time zone.
ZoneId z = ZoneId.of( "America/Phoenix" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
Extract the date portion.
LocalDate ld = zdt.toLocalDate() ;
Generate text representing the value of that LocalDate object.
String iso8601 = ld.toString() ;
Or automatically localize.
Locale locale = Locale.US ;
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDate( FormatStyle.SHORT ).
String localized = ld.format( f ) ;
You said:
My server is in MST
First, servers should generally be kept to a default time zone of UTC, that is no zone, just an offset of zero hours-minutes-seconds.
Secondly, as a Java programmer, write your code without depending on the default time zone. Specify explicitly the desired time zone by passing the otherwise optional time zone argument to the various date-time methods.
Thirdly, MST is not a real time zone.
Hey I have Iso Format date. I want to compare with current date. If date is equal to current date, I need the time of given Iso date and otherwise i need date.
val date = "2021-10-01T18:39:10.0492422+01:00"
How to compare today’s date with this value. If date is match i need time in HH:MM otherwise dd MMM YYYY format.
Important thing my minSdkVersion 21
tl;dr
Java syntax, as I don’t know Kotlin:
LocalDate
.now( ZoneId.of( "America/Edmonton" ) )
.isEqual(
OffsetDateTime
.parse( "2021-10-01T18:39:10.0492422+01:00" )
.atZoneSameInstant( ZoneId.of( "America/Edmonton" ) )
.toLocalDate()
)
As for generating text from java.time objects in specific formats using DateTimeFormatter and DateTimeFormatterBuilder classes, that has been covered many many times already. Search to learn more.
Details
The latest Android tooling brings much of the java.time functionality built into Android 26+ to earlier Android via “API de-sugaring”.
In Java syntax…
Parse your input as a OffsetDateTime.
OffsetDateTime odt = OffsetDateTime.parse( "2021-10-01T18:39:10.0492422+01:00" ) ;
Adjust to the time zone by which you perceive “today’s date”.
ZoneId z = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;
Get today’s date as seen in your target time zone, a LocalDate.
LocalDate today = LocalDate.now( z ) ;
Compare to the date of our input as seen in the same time zone.
boolean sameDate = today.isEqual( zdt.toLocalDate() ) ;
As seen above, you must provide a time zone. For any given moment, the date varies around the globe by time zone. Right now is “tomorrow” in Tokyo Japan while simultaneously “yesterday” in Toledo Ohio US. So to ask “what is the date today?”, you must also specify where, that is, by what time zone do you want to perceive the current date.
This question already has answers here:
Change date format in a Java string
(22 answers)
Closed 4 years ago.
I want to display complete date in mySQL format but don't want to see the Time along with it.
Wanted to increment or decrement the date to perform actions
tl;dr
myResultSet.getObject( … , Instant.class )
.atZone( ZoneId.of( "Pacific/Auckland" ) )
.toLocalDate()
.toString()
Details
For a column of type akin to the SQL-standard TIMESTAMP WITH TIME ZONE, retrieve as a Instant.
Instant instant = myResultSet.getObject( … , Instant.class ) ;
An Instant is always in UTC. Adjust into the time zone by which you want to perceive the date according to the wall-clock time used by the people of a certain region. For any given moment, the date varies around the world by zone. It might be “tomorrow” in Asia/Kolkata India while still “yesterday” in America/Montreal Canada.
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
Extract the date-only, as that is what you want to focus on.
LocalDate ld = zdt.toLocalDate() ;
Use the various plus/minus methods to add or subtract days, weeks, months, years, or a combination of those (Period).
LocalDate dayAfter = ld.plusDays( 1 ) ;
Or…
Period p = Period.parse( "P3M7D" ) ;
LocalDate later = ld.plus( p ) ;
For a database type akin to SQL-standard TIMESTAMP WITHOUT TIME ZONE, retrieve as a LocalDateTime. Skip the part above with time zone. Go directly to extracting the LocalDate. Proceed with your addition/subtraction.
myResultSet.getObject( … , LocalDateTime.class )
.toLocalDate()
.plusDays( 1 )
.toString()
To generate a String representing the date value in standard ISO 8601 format, call LocalDate::toString(). For other formats, use DateTimeFormatter. Search Stack Overflow to learn more.
I just want to calculate time difference in minutes, hopefully there is already a class which does it correctly.
So the values which I get from the website are only Hours and Minutes (for instance: event starts at: 20:30 and ends at 03:30).
When I use 'Duration.between' I get incorrect values - it is happening when the first value is greater than second or second is past midnight.
I think I would be able to do this with 'ifs' and 'elses' but I am sure that there is already a class or a method which would solve the issue in more elegant way, but I can't find it.
Here is my code: it works only when the second value is greater than first:
LocalTime eventStarts = LocalTime.now();
LocalTime eventEnds = LocalTime.now();
eventStarts = eventStarts.withHour(22).withMinute(00);
eventEnds = eventEnds.withHour(03).withMinute(00);
Duration durationBetweenEvents = Duration.between(eventStarts, eventEnds);
System.out.println(durationBetweenEvents.toMinutes());
in this case i get '-1140'
Just add the following to your code.
if (durationBetweenEvents.isNegative()) {
durationBetweenEvents = durationBetweenEvents.plusDays(1);
}
You have to be a little careful with daylight savings. Your calculation can be an hour out, if daylight savings time starts or ends between the events. But without knowing date or timezone information, there's no way to deal with that.
Need dates & time zone
LocalTime has no notion of dates or days. So it is limited to a single generic 24-hour day. Going from an evening time to a morning time is viewed as going backwards in time, not wrapping around to another day as no days exist.
To know the duration of an actual event you need dates and time zone.
Getting the current date requires a time zone. For any given moment, the date varies around the globe by zone.
Once you have dates, apply a ZoneId to get ZonedDateTime objects. From there you can get a Duration that takes into account anomalies such as Daylight Saving Time (DST).
ZoneId z = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( z );
LocalDate tomorrow = today.plusDays( 1 );
ZonedDateTime zdtStart =
ZonedDateTime.of( today , LocalTime.parse( "20:30" ) , z ) ;
ZonedDateTime zdtStop =
ZonedDateTime.of( tomorrow , LocalTime.parse( "03:30" ) , z ) ;
Duration d = Duration.between( zdtStart , zdtStop ) ;
long totalMinutes = d.toMinutes() ;
zdtStart.toString(): 2017-04-13T20:30-04:00[America/Montreal]
zdtStop.toString(): 2017-04-14T03:30-04:00[America/Montreal]
d.toString(): PT7H
totalMinutes: 420
See this code run live at IdeOne.com.
sample:
Long timeStamp = 1466058808;
Time time = new Time(timeStamp );
DateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
System.out.println(format.format(time));
print is: 2016-05-31 08:19:07
How can I get expected results is : 2016-05-31 00:00:00
Thanks!
And finally get the time stamp of 2016-05-31 00:00:00 This is what i want
So anyone know how to make it?
Simple, use:
DateFormat format = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
Or if you want a long (and have java 8):
LocalDateTime.ofEpochSecond(1466058808, 0, ZoneOffset.UTC).toLocalDate().atStartOfDay().toEpochSecond(ZoneOffset.UTC)
java.time
The Answer by krzyk is close but ignores the crucial issue of time zone. Let's try that again using the java.time framework built into Java 8 and later. Much of java.time functionality is back-ported to Java 6 & 7 (ThreeTen-Backport) and further adapted to Android (ThreeTenABP).
Count of seconds from epoch
You do not say so in the Question, but we assume the Long of 1466058808 is a number of whole seconds from the epoch of first moment of 1970 in UTC.
Instant
First we convert that to an Instant, a moment on the timeline in UTC.
Instant instant = Instant.ofEpochSecond( 1466058808L );
Time Zone
Determining a date, and the start of the day, depends on a time zone. For any given moment, the date can vary around the world by time zone. A few moments after midnight in Paris is still “yesterday” in Montréal.
ZonedDateTime
You can make wide use of Instant in your code. Generally best practice is to perform business logic, data storage, logging, and so on in UTC. Apply a time zone only where required such as display to a user. Apply a ZoneId to get a ZonedDateTime.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
Using LocalDate for start-of-day
To get the start of the day we need to go through the LocalDate class. Note that we should always pass the optional time zone argument. If omitted, the JVM’s current default time zone is implicitly applied. That default can change at any time, even during runtime, as any code in any app of the JVM can make a call to TimeZone.setDefault. Better to be specific.
LocalDate localDate = zdt.toLocalDate();
ZonedDateTime startOfDay = localDate.atStartOfDay( zoneId );
Note that you should not assume the day starts at 00:00:00.0. Daylight Saving Time (DST) may mean the day starts at a different wall-clock time.
One-liner
I do not recommend doing so, but you can combine all this into a single line.
ZonedDateTime startOfDay = ZonedDateTime.ofInstant( Instant.ofEpochSecond( 1466058808L ) , ZoneId.of( "America/Montreal" ) ).toLocalDate().atStartOfDay( ZoneId.of( "America/Montreal" ) );
use a Calendar, so you can extract date properties:
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(millis);
//getting the desired properties
cal.get(Calendar.YEAR);
cal.get(Calendar.MONTH);
cal.get(Calendar.DAY_OF_MONTH);