Is there a better way to zero out Calendar date? - java

I'm looking to see if there is a better way in obtaining the same result as the following code:
Calendar date = Calendar.getInstance();
date.setTimeInMillis(System.currentTimeMillis());
date.set(Calendar.HOUR_OF_DAY, 0);
date.set(Calendar.MINUTE, 0);
date.set(Calendar.SECOND, 0);
date.set(Calendar.MILLISECOND, 0);
I'm using this to be able to compare the difference in days between two dates. I am currently coding for target API 24 and am not interested in using Joda Time for such a simple task.
I've come up with the following function, but would love to hear if there is a simpler, perhaps built in, method for either zeroing out the date or an entire different method for getting the amount of days between two dates.
private long getFlatDateInMillis() {
Calendar currentDate = Calendar.getInstance();
currentDate.setTimeInMillis(System.currentTimeMillis());
currentDate.set(Calendar.HOUR_OF_DAY, 0);
currentDate.set(Calendar.MINUTE, 0);
currentDate.set(Calendar.SECOND, 0);
currentDate.set(Calendar.MILLISECOND, 0);
return currentDate.getTimeInMillis();
}
That way, I could quickly use:
Calendar date = getFlatDateInMillis();
I just want to make sure I'm not missing anything that is simpler, already pre-defined.
Thank you!

The correct way to do this is with the java.time.LocalDate class. It stores only the date, not the time, and it has a now() static method, which returns the current day.
LocalDate today = LocalDate.now();
If you're looking at Android, this was added at API level 26, but there are other ways of using the "new style" date classes with Android, such as the ThreeTen-Backport library.

tl;dr
ChronoUnit.DAYS.between( // Calculate elapsed time between a pair of `LocalDate` date-only objects. Returns a total number of elapsed days.
( (GregorianCalendar) myJavaUtilCal ) // Cast your legacy `java.util.Calendar` object to the subclass `java.util.GregorianCalendar`, also legacy.
.toZonedDateTime() // Convert from legacy `GregorianCalendar` to modern `ZonedDateTime` class.
.toLocalDate() , // Extract the date-only value, a `LocalDate`, lacking time-of-day and lacking time zone.
otherLocalDate // Compare to some other `LocalDate` object.
) // Returns a `long` number of days. Uses Half-Open approach where the beginning is *inclusive* while the ending is *exclusive*.
Details
The Answer by Kareem is correct. Some more thoughts here.
Is there a better way to zero out Calendar date?
Yes, there is a better way: don’t.
Trying to clear out the time-of-day on a date+time types is the wrong approach; use a date-only type instead (LocalDate).
And don’t use the troublesome old legacy classes such as Calendar, Date, SimpleDateFormat as they are now supplanted by the java.time classes.
the difference in days between two dates
First convert your legacy Calendar object to the modern ZonedDateTime class. To convert, call new methods added to the old classes.
GregorianCalendar myGregCal = (GregorianCalendar) myJavaUtilCal ; // Cast from superclass to subclass.
ZonedDateTime zdt = myGregCal.toZonedDateTime() ; // Convert from legacy class to modern class.
Extract the date-only value.
LocalDate ld = zdt.toLocalDate() ; // Extract date-only object from date-time object.
Calculate elapsed time in days
long days = ChronoUnit.DAYS.between( ld , otherLd ) ;
Or represent the elapsed time as a Period.
Period p = Period.between( ld , otherLd ) ;
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, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

EDIT: Thanks to Basil and Kareem, I've updated to the following code (so, so much easier):
Added to gradle.build:
compile 'com.jakewharton.threetenabp:threetenabp:1.0.5'
Then, in my activity, etc,
AndroidThreeTen.init(this);
LocalDate today = LocalDate.now();
LocalDate anotherDay = LocalDate.of(2019, 3, 25);
long dayDifference = ChronoUnit.DAYS.between(today, anotherDay); //dayDifference = 365
One thing of note is that Calendar references months starting at 0 index, whereas LocalDate references months starting at 1 index.

Related

Why get different localDate with same timezone

java.sql.Date date = java.sql.Date.valueOf("1900-01-01");
org.joda.time.LocalDate localDate = new org.joda.time.LocalDate(date);
Based above code, I did some tests as below:
Question #1 why do I get different localDate object with same timezone?
If I change local timezone to UTC+8 Singapore Timezone, will get 1899-12-31
If I change local timezone to UTC+8 China Timezone, will get 1900-01-01
Question #2 why do I get same time with different timezone?
If I change local timezone to UTC-8 America/Los_Angeles Timezone, will get 1900-01-01
If I change local timezone to UTC+8 China Timezone, will get 1900-01-01
Could someone help clarify that?? it is little bit confused.
In 1900, Singpore's offset is UTC +6:55:25, so when you create date 1900-01-01 in Singapore time zone, it should be 1899-12-31T17:04:35Z[UTC] as below:
java.time.ZonedDateTime localDateTime = ZonedDateTime.of(1900, 01, 01, 0,
0, 0, 0, ZoneId.of("Singapore"));
System.out.println(localDateTime.withZoneSameInstant(ZoneId.of("UTC")));
// 1899-12-31T17:04:35Z[UTC]
However, when you use java.sql.Date, it use wrong offset UTC +08:00:
TimeZone.setDefault(TimeZone.getTimeZone("Singapore"));
java.sql.Date date = java.sql.Date.valueOf("1900-01-01");
java.time.Instant instant = Instant.ofEpochMilli(date.getTime());
System.out.println(instant); // 1899-12-31T16:00:00Z
and when you create org.joda.time.LocalDateTime with this wrong value, Joda use UTC +6:55:25 as offset, resulting in a date time 1899-12-31T16:00:00 + 6:55:25:
org.joda.time.LocalDateTime singaporeDateTime = new org.joda.time.LocalDateTime(date);
System.out.println(singaporeDateTime); // 1899-12-31T22:55:25.000
You can use the similar approach to check the result of Shanghai and Los Angelas, the point is, avoid using java.sql.Date and other deprecated date time related classes. Use java.time instead if you are working with java8 or higher.
tl;dr
java.time.LocalDate
.of(
1900 ,
Month.JANUARY ,
1
) ;
Avoid legacy date-time classes
You are using a terrible old class java.sql.Date that was badly designed with flawed hacks. Among its problems is that it pretends to represent a date-only value but actually holds a time-of-day. It even holds a time zone deep inside, though without getter or setter. Never use this class. Supplanted years ago by the java.time.LocalDate class.
The Joda-Time project too is supplanted by the java.time classes. The project is in maintenance mode, receiving updates and critical bug fixes but no new feature work. The project advises migration to the java.time classes. Migration is easy as they share similar concepts, both having been led by the same man, Stephen Colebourne.
java.time.LocalDate
Use java.time.LocalDate when you want a date-only value without time-of-day and without time zone. All your problems raised in your Question go away.
java.time.LocalDate ld = LocalDate.of( 1900 , Month.JANUARY , 1 ) ; // Simply a year-month-day date, no problems, no issues, no confusion.
ld.toString(): 1900-01-01
Also notice that java.time uses sane numbering where 2018 means the year 2018, and 1-12 means January-December. This is in distinct contrast to the troublesome legacy classes.
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.

Convert calendar String to Calendar Object in java

I wan't to convert a string Calendar Object (calendar.toString()) to calendar object.
I tried this solution but it show in console the date of the day '12-05-2017' not '02-02-2017'
String calendar object format:
java.util.GregorianCalendar[time=1485993600000,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Africa/Casablanca",offset=0,dstSavings=3600000,useDaylight=true,transitions=102,lastRule=java.util.SimpleTimeZone[id=Africa/Casablanca,offset=0,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=10800000,endTimeMode=0]],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2017,MONTH=1,WEEK_OF_YEAR=5,WEEK_OF_MONTH=1,DAY_OF_MONTH=2,DAY_OF_YEAR=33,DAY_OF_WEEK=5,DAY_OF_WEEK_IN_MONTH=1,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=0,ZONE_OFFSET=0,DST_OFFSET=0]
Calendar calendar = GregorianCalendar.getInstance();
calendar.setTime(new Date("2017/02/02"));
System.out.println("calendar : "+calendar.getTime());
try {
GregorianCalendar gc = new GregorianCalendar();
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy");
System.out.println("calendar : "+calendar.getTime());
gc.setTimeZone(TimeZone.getTimeZone(calendar.toString()));
System.out.println("tme zone : "+gc.getTimeZone());
System.out.println("calendar : "+calendar.getTime());
System.out.println("calendar : "+calendar.toString());
System.out.println(formatter.format(gc.getTime()));
}
catch(Exception e) {
//If exception, return server TimeStamp
}
Any help please
If that were me, I’d look at all the setters of both Calendar and GregorianCalendar and see if I thought I could extract the values needed for the setters from the string. “time=1485993600000” should give you the most important information, the time, and you can feed it into setTimeInMillis(). You ought to be able to get a time zone out of “Africa/Casablanca”. And so forth. You can probably use regular expressions for extracting the fields from the string.
You’d probably have to live with not covering all cases. Your particular GregorianCalendar seems to contain a sun.util.calendar.ZoneInfo and a java.util.SimpleTimeZone; I don’t know whether that is always the case nor what other possibilities there are.
The strict test of your attempt is easy: just call toString() again on your newly constructed instance and see if you get the same string. The difficulty comes if you accept some differences and you need to determine whether the actual differences lie within what you have decided to accept.
Or really, I wouldn’t want to bother if I could avoid it. I’d see if I could find an easier task or an easier way to obtain what you are really trying to obtain. As I already said in a comment, one may use java.time.LocalDate instead of GregorianCalendar. LocalDate.parse() will readily parse the string from LocalDate.toString(), and the problem is solved. Just to give one example of another way to look at it.
In your code, you have two separate GregorianCalendar objects - one called calendar and one called gc. You're setting one calendar object to the date that you want, then printing out the other one.
Thanks #Ole , I finally found the solution and it works.
Calendar calendar = Calendar.getInstance();;
calendar.setTime(new Date("2017/02/02"));
String[] ds = calendar.toString().split("=");
String[] ds2 = ds[1].split(",");
try {
Calendar cal = Calendar.getInstance();;
DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy");
cal.setTimeInMillis(Long.valueOf(ds2[0]));
System.out.println(formatter.format(cal.getTime()));
}
catch(Exception e) {
}
java.time
You are using terrible old classes that are now supplanted by the much superior java.time classes.
Instantiate a LocalDate. The LocalDate class represents a date-only value without time-of-day and without time zone.
LocalDate ld = LocalDate.parse( "2017-02-02" ) ;
To generate a string in standard ISO 8601 format, call toString.
String output = ld.toString() ;
2017-02-02
For other formats use the DateTimeFormatter class.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd-MM-uuuu" ) ;
String output = ld.format( f ) ;
02-02-2017
Your Question is not clear. If the problem is that your code is being handed a GregorianCalendar object, convert it to java.time.ZonedDateTime. Call new conversion methods added to the old classes.
if( myCalendar instanceOf GregorianCalendar ) {
ZonedDateTime zdt = myCalendar.toZonedDateTime() ;
}
Extract the date-only value you desire, as a LocalDate.
LocalDate ld = zdt.toLocalDate() ;
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.

find current Date and day after tomorrow's date in java

How to find current date in java. I found a lot but every time i got same command
Date d = new Date(); or something similar
Every such command returns a date of 1970 year.
I fail to understand, Whats the benefit of this getting a date of 1970 ?
Is there any way where i can get current time and add a second into it.
My real purpose is to convert a long value into Date and add a second in it.
5:40:12 should give me 5:40:13 after adding a second.
Any help would be appreciated as i am fed up getting 1970 date.
My real purpose is to convert a long value into Date and add a second in it. 5:40:12 should give me 5:40:13 after adding a second
The troublesome java.util.Date class is now legacy, supplanted by the java.time classes.
Instant.ofEpochMilli( yourLongIntegerGoesHere ) // A moment on the timeline in UTC represented a count of nanoseconds since the epoch of `1970-01-01T00:00:00Z`.
.atZone( ZoneId.of( "Pacific/Auckland" ) // Time zone for the region whose wall-clock time you want to see.
.plusSeconds( 1 )
.toLocalTime() // Extract just the time-of-day without date and without time zone.
.toString() // Generate a string representing the time-of-day value in standard ISO 8601 format.
05:40:13
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.
Java.Util.Date class is deprecated, I would recommend using
Java.Util.Calendar instead.
If you're looking to add a second to Current date, try something like this:
Calendar currentTime = Calendar.getInstance(); // gets a calendar using the default time zone and locale.
calendar.add(currentTime.SECOND, 1);
System.out.println(currentTime.getTime());
BUT, the reason why you are receiving a 1970 date when using the Date class is because that class works with milliseconds, so you must multiply the long value by 1000 in order for it to convert to a date, here's an example.
Date currentDate = new Date( YourLongValue * 1000);

Java Calendar Not Changing Values

I am writing an application to receive past stock data in java.
I am using a Calendar to chose the to and from dates when calculating a six day average however this is not working due to the to calendar being the same as the from despite subtracting days in the latter...
private BigDecimal calcMovingAvg(int days, Calendar start){
Calendar to = start;
int temp = Functions.weekdays(start.getTime(), days);
temp = temp - (2 * temp);
start.add(start.DAY_OF_MONTH, temp);
BigDecimal d = new BigDecimal(String.valueOf(days));
List<HistoricalQuote> histQuotes = null;
try {
//Calling a method to get stock history between start and to date
histQuotes = stk.getHistory(start, to, Interval.DAILY);
System.out.println(histQuotes);
} catch (IOException e) {
e.printStackTrace();
}
Start is already defined and working
I save to = start so as to have an end date when taking the previous 6 days for averaging
Functions.weekdays calculates how many of those 6 days were actually weekdays (business days) and adjusts the number accordingly (temp is the number of days needed to get 6 business days).
When comparing, I am getting start == to, why is start not changing?
Calendar to = (Calendar) start.clone();
int temp = Functions.weekdays(start.getTime(), days);
temp = temp - (2 * temp);
start.add(start.DAY_OF_MONTH, temp);
The calendar was using the same instance. Cloning the calendar solved the issue as it created two separate entities.
java.time
This work is easier with the java.time framework built into Java 8 and later. Avoid using the old date-time classes such as java.util.Calendar as they haven proven to be poorly designed and troublesome.
Immutable Objects
The java.time classes use immutable objects, generating new objects based on the old ones’ values rather than changing (”mutating“) the original. This approach prevents the problem encountered in the Question.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now( zoneId );
ZonedDateTime later = now.plusWeeks( 1 ); // Generates a second object without modifying the first.
Convert
Best to avoid the old classes entirely, including java.util.Date and java.util.Calendar. But if you must, you can convert.
New methods have been added to the old classes to facilitate conversion.
Call GregorianCalendar::toZonedDateTime to generate an equivalent ZonedDateTime object. I your Calendar object is indeed a GregorianCalendar, downcast.
if( cal instanceof GregorianCalendar ) {
GregorianCalendar gCal = ( GregorianCalendar ) cal; // Cast. Down-casting from interface to concrete class.
ZonedDateTime zdt = gCal.toZonedDateTime();
}
Call the static method GregorianCalendar.from( ZonedDateTime) to get a GregorianCalendar object (which implements the Calendar interface) from a ZonedDateTime.
java.util.Calendar cal = java.util.GregorianCalendar.from( later );
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Java8 java.util.Date conversion to java.time.ZonedDateTime

I am getting the following exception while trying to convert java.util.Date to java.time.LocalDate.
java.time.DateTimeException: Unable to obtain ZonedDateTime from TemporalAccessor: 2014-08-19T05:28:16.768Z of type java.time.Instant
The code is as follow:
public static Date getNearestQuarterStartDate(Date calculateFromDate){
int[] quaterStartMonths={1,4,7,10};
Date startDate=null;
ZonedDateTime d=ZonedDateTime.from(calculateFromDate.toInstant());
int frmDateMonth=d.getMonth().getValue();
Is there something wrong in the way I am using the ZonedDateTime class?
As per documentation, this should convert a java.util.Date object to ZonedDateTime. The date format above is standard Date?
Do I have to fallback on Joda time?
If someone could provide some suggestion, it would be great.
To transform an Instant to a ZonedDateTime, ZonedDateTime offers the method ZonedDateTime.ofInstant(Instant, ZoneId). So
So, assuming you want a ZonedDateTime in the default timezone, your code should be
ZonedDateTime d = ZonedDateTime.ofInstant(calculateFromDate.toInstant(),
ZoneId.systemDefault());
To obtain a ZonedDateTime from a Date you can use:
calculateFromDate.toInstant().atZone(ZoneId.systemDefault())
You can then call the toLocalDate method if you need a LocalDate. See also: Convert java.util.Date to java.time.LocalDate
The Answer by assylias and the Answer by JB Nizet are both correct:
Call the new conversion method added to the legacy class, java.util.Date::toInstant.
Call Instant::atZone, passing a ZoneId, resulting in a ZonedDateTime.
But your code example is aimed at quarters. For that, read on.
Quarters
No need to roll-your-own handling of quarters. Use a class already written and tested.
org.threeten.extra.YearQuarter
The java.time classes are extended by the ThreeTen-Extra project. Among the many handy classes provided in that library you will find Quarter and YearQuarter.
First get your ZonedDateTime.
ZonedId z = ZoneID.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = myJavaUtilDate.toInstant().atZone( z ) ;
Determine the year-quarter for that particular date.
YearQuarter yq = YearQuarter.from( zdt ) ;
Next we need the start date of that quarter.
LocalDate quarterStart = yq.atDay( 1 ) ;
While I do not necessarily recommend doing so, you could use a single line of code rather than implement a method.
LocalDate quarterStart = // Represent a date-only, without time-of-day and without time zone.
YearQuarter // Represent a specific quarter using the ThreeTen-Extra class `org.threeten.extra.YearQuarter`.
.from( // Given a moment, determine its year-quarter.
myJavaUtilDate // Terrible legacy class `java.util.Date` represents a moment in UTC as a count of milliseconds since the epoch of 1970-01-01T00:00:00Z. Avoid using this class if at all possible.
.toInstant() // New method on old class to convert from legacy to modern. `Instant` represents a moment in UTC as a count of nanoseconds since the epoch of 1970-01-01T00:00:00Z.
.atZone( // Adjust from UTC to the wall-clock time used by the people of a particular region (a time zone). Same moment, same point on the timeline, different wall-clock time.
ZoneID.of( "Africa/Tunis" ) // Specify a time zone using proper `Continent/Region` format. Never use 2-4 letter pseudo-zone such as `PST` or `EST` or `IST`.
) // Returns a `ZonedDateTime` object.
) // Returns a `YearQuarter` object.
.atDay( 1 ) // Returns a `LocalDate` object, the first day of the quarter.
;
By the way, if you can phase out your use of java.util.Date altogether, do so. It is a terrible class, along with its siblings such as Calendar. Use Date only where you must, when you are interfacing with old code not yet updated to java.time.
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.
The answer didn't work for me on Java 10 storing util.Date in UTC.
Date.toInstant() seems to convert the EpochMillis into the local time zone of the server.
ZDT.ofInstant(instant, zoneId) and instant.atZone(zoneId) seem to just tag on a TZ on the instant, but it's already messed up with.
I couldn't find a way to prevent Date.toInstant() from messing with the UTC time with the system time zone.
The only way I found to work around this was to go through the sql.Timestamp class:
new java.sql.Timestamp(date.getTime()).toLocalDateTime()
.atZone(ZoneId.of("UTC"))
.withZoneSameInstant(desiredTZ)

Categories