new Date() deprecated in open jdk 11? or no supported - java

I'm having an issue with Date library current week. When you google it's week 11, but my function returns 12. In terms of location, I am in South Africa, but the same issue is reported by someone in Germany who is testing the application. I wrote below code to test this in a small piece of code and I see when I get calendar using new Date() library, it's returning 12, but when I use Localdate.now() it's returning 11.
I updated the Dockerfile jdk initially it was jdk8 and now it's openjdk11. Can this be the reason I am getting different results? Is new Date() no longer supported in Java 11?
Below is the code snippet. I would love if some can assist me on this.
package com.company;
import java.time.LocalDate;
import java.time.temporal.ChronoField;
import java.util.Calendar;
import java.util.Date;
public class CalenderLibrary {
private static Calendar cal = Calendar.getInstance();
public static void main(String[] args) {
Date date = new Date();
String calendarWeekFromEvent = getCalendarWeekFromEventWithDate(date);
System.out.println("Date: {} " + calendarWeekFromEvent);
LocalDate localDate = LocalDate.now();
String localDate1 = getCalendarWeekFromEventWithLocalDate(localDate);
System.out.println("LocalDate: {} " + localDate1);
}
private static String getCalendarWeekFromEventWithLocalDate(LocalDate date) {
return String.valueOf(date.get(ChronoField.ALIGNED_WEEK_OF_YEAR));
}
private static String getCalendarWeekFromEventWithDate(Date date) {
cal.setTime(date);
return String.valueOf(cal.get(Calendar.WEEK_OF_YEAR));
}
}
Results:
Date: {} 12
LocalDate: {} 11

java.util.Date and java.util.Calendar are not deprecated, and still work as they always have. However, how they work is difficult to use, which is why java.time classes are recommended instead.
What you are seeing is the difference between WEEK_OF_YEAR (which depends on the locale) and ALIGNED_WEEK_OF_YEAR (which is the same in all locales).
When setting or getting the WEEK_OF_MONTH or WEEK_OF_YEAR fields, Calendar must determine the first week of the month or year as a reference point. The first week of a month or year is defined as the earliest seven day period beginning on getFirstDayOfWeek() and containing at least getMinimalDaysInFirstWeek() days of that month or year. Weeks numbered ..., -1, 0 precede the first week; weeks numbered 2, 3,... follow it. Note that the normalized numbering returned by get() may be different. For example, a specific Calendar subclass may designate the week before week 1 of a year as week n of the previous year.
ALIGNED_WEEK_OF_YEAR represents concept of the count of weeks within the period of a year where the weeks are aligned to the start of the year. This field is typically used with ALIGNED_DAY_OF_WEEK_IN_YEAR.
For example, in a calendar systems with a seven day week, the first aligned-week-of-year starts on day-of-year 1, the second aligned-week starts on day-of-year 8, and so on. Thus, day-of-year values 1 to 7 are in aligned-week 1, while day-of-year values 8 to 14 are in aligned-week 2, and so on.
And for the locale difference:
// returns DayOfWeek.MONDAY
WeekFields.of(Locale.forLanguageTag("de-DE")).getFirstDayOfWeek();
// returns DayOfWeek.SUNDAY
WeekFields.of(Locale.forLanguageTag("en-ZA")).getFirstDayOfWeek();
To get the unaligned week of year using the current system local with java.time:
LocalDate.now().get(WeekFields.of(Locale.getDefault()).weekOfYear())
If you want to be locale-independent, then there is ISO.weekOfYear() if you want the week to start on a Monday, and SUNDAY_START.weekOfYear() for a Sunday.

The old, much-derided Date and Calendar classes have always been confusing and difficult to use properly, particularly in a multi-threaded context.Java 8’s JSR 310 implementation offers specific classes for:
The old date library included only a single time representation class – java.util.Date, which despite its name, is actually a timestamp. It only stores the number of milliseconds elapsed since the Unix epoch.

Related

Cannot Convert Date '0001-01-01' from Java to C# correctly

I try to provide a tool to convert datetime from Java to C#. But there is a serious problem.
In Java, I read '0001-01-01' from the SQL Server database via java.sql.Date, and get the millisecond -62135798400000.
I also consider the timezone offset.
private static long getMilliSecondWithoutTimeZone(long origin) {
return origin + (ZonedDateTime.now().getOffset().getLong(OFFSET_SECONDS) * 1000);
}
And the final millisecond is -62135769600000.
In C#, I use this millisecond to new Datetime
var ticks = new DateTime(1970, 1, 1).Ticks + (-62135769600000 * 10000);
var date = new DateTime(ticks);
When the code runs, it will throw the exception:
System.ArgumentOutOfRangeException: 'Ticks must be between DateTime.MinValue.Ticks and DateTime.MaxValue.Ticks. (Parameter 'ticks')'
However, the conversion is correct after '1600-01-01' according to my test.
Before '1600-01-01', there always is a few days of error.
It makes me very confused.
I find the remarks in https://learn.microsoft.com/en-us/dotnet/api/system.globalization.juliancalendar?view=net-5.0#remarks
The Gregorian calendar was developed as a replacement for the Julian calendar (which is represented by the JulianCalendar class) and was first introduced in a small number of cultures on October 15, 1582. When working with historic dates that precede a culture's adoption of the Gregorian calendar, you should use the original calendar if it is available in the .NET Framework. For example, Denmark changed from the Julian calendar to the Gregorian calendar on February 19 (in the Julian calendar) or March 1 (in the Gregorian calendar) of 1700. In this case, for dates before the adoption of the Gregorian calendar, you should use the Julian calendar. However, note that no culture offers intrinsic support for the JulianCalendar class. You must use the JulianCalendar class as a standalone calendar. For more information, see Working with calendars.
The actual reason is:
C# uses the Gregorian calendar all the time.
Java uses the Gregorian calendar after October 15, 1582, and uses the Julian calendar before.
The solution:
import java.sql.Date;
import java.time.chrono.IsoChronology;
import java.time.*;
public class Test {
public static Long getMilliSeconds(Date date) {
if (null == date) {
return null;
}
IsoChronology ISO = IsoChronology.INSTANCE;
LocalDate ld = date.toLocalDate();
return ISO.localDateTime(LocalDateTime.of(ld.getYear(), ld.getMonth(), ld.getDayOfMonth(), 0, 0, 0)).toInstant(ZoneOffset.UTC).toEpochMilli();
}
}
It seems like the millisecond value that you mention, -62_135_798_400_000, comes out of an old-fashioned java.sql.Date object created in a timezone that is assumed to be at UTC offset +08:00 back then, perhaps just Etc/GMT-8. With this assumption, the value is historically correct since it was the Julian calendar that was used back then, and Date does use that.
I don’t know the .NET classes that C# uses, but I consider it a likely that a few days error are caused by them using the proleptic Gregorian calendar, that is, pretending that the Gregorian calendar was used in all past even though it didn’t come into existence before 1582. The modern Java date and time API does this and therefore gives you millisecond values that usually differ by a few days.
long milliseconds = LocalDate.of(1, 1, 1)
.atStartOfDay(ZoneOffset.ofHours(8))
.toInstant()
.toEpochMilli();
System.out.format(Locale.ENGLISH, "%,d%n", milliseconds);
Output:
-62,135,625,600,000
It is 48 hours — or 2 days — later than the time you mentioned. See if it solves your issue.
Link
Oracle tutorial: Date Time explaining how to use java.time.
You forgot to account for time zone offset.
If we set the time zone to UTC, you'll see this:
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
System.out.println(new Date(-62135798400000L));
Output
Fri Dec 31 16:00:00 UTC 1
It is actually year 1 BC, not year 1 AD.
The time 16:00 indicates a time zone offset of 8 hours, so if we change to GMT+8 we get:
TimeZone.setDefault(TimeZone.getTimeZone("GMT+8"));
System.out.println(new Date(-62135798400000L));
Output
Sat Jan 01 00:00:00 GMT+08:00 1
That is correctly year 1 AD.
Which means that you need to adjust the millisecond value by 8 hours, aka 28800000 milliseconds.
For the date 0001-01-01 00:00 UTC, the correct value for milliseconds is -62135769600000. Anything less than that will be rejected by the C# DateTime class.

Inconsistency in java date library for week of year

As per https://en.wikipedia.org/wiki/ISO_8601#Week_dates, Weekdays start on Monday. But, from Java, if you try to extract week number in two different ways, two different outputs come if the date is a Sunday.
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class TestDate {
public static void main(String[] args) throws ParseException {
final SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
final SimpleDateFormat weekFormatter = new SimpleDateFormat("ww");
String date = "2018-10-21";
System.out.println(weekFormatter.format(formatter.parse(date)));
Calendar calendar = Calendar.getInstance();
calendar.setFirstDayOfWeek(Calendar.MONDAY);
calendar.setTime(formatter.parse(date));
System.out.println(calendar.get(Calendar.WEEK_OF_YEAR));
}
}
Output:
43
42
Is this an inconsistency?
This is just a test program I wrote to reproduce the issue, I noticed the problem in Hive, like the following:
0: jdbc:hive2://zk0-something> select from_unixtime(t, 'ww'), weekofyear(from_unixtime(t, 'yyyy-MM-dd')) from (select 1540122033 as t) a;
+------+------+--+
| _c0 | _c1 |
+------+------+--+
| 43 | 42 |
+------+------+--+
1 row selected (0.388 seconds)
0: jdbc:hive2://zk0-something>
java.time
String date = "2018-10-21";
LocalDate ld = LocalDate.parse(date);
int weekOfYear = ld.get(WeekFields.ISO.weekOfYear());
System.out.println(weekOfYear);
Output:
42
Since you are interested in the ISO 8601 rules for week numbers, use WeekFields.ISO for getting week related data from a LocalDate. You may also use a formatter if you like:
DateTimeFormatter weekFormatter = DateTimeFormatter.ofPattern("ww", Locale.FRANCE);
System.out.println(ld.format(weekFormatter));
Output is the same:
42
The locale passed to DateTimeFormatter.ofPattern determines the week scheme. If I pass Locale.US instead, I get 43.
I recommend you use java.time, the modern Java date and time API, and stay away from the old date-time classes like SimpleDateFormat and Calendar. The old ones were poorly designed and the modern ones are much nicer to work with.
What went wrong in your code?
Both the outdated SimpleDateFormat class and the modern DateTimeFormatter take their week numbering scheme from their locale. If no locale is specified for the formatter, it uses the default locale of the JVM. So if the JVM has American locale, for example, the formatter will print 43 in your first example because in the US Sunday October 21 this year was in week 43. If the locale is French, it will print 42 because that day was in week 42 in France. France follows the ISO 8601 standard, the USA does not.
In your example, setting the Calendar’s first day of week to Monday causes the week number to be 42 as you had expected. This will not always be the case, however. Week numbers are defined not only by the first day of the week but also by the definition of week 1. From your link:
The first ISO week of a year may have up to three days that are
actually in the Gregorian calendar year that is ending; if they are
Monday, Tuesday and Wednesday. Similarly, the last ISO week of a year
may have up to three days that are actually in the Gregorian calendar
year that is starting; if they are Friday, Saturday, and Sunday. The
Thursday of each ISO week is always in the Gregorian calendar year
denoted by the ISO week-numbering year.
The American definition of which week is week 1 is different: In the US January 1 is always in week 1. Therefore if your Calendar is created with American locale, setting its first day of week to Monday is not enough to make is follow ISO 8601 rules. Coincidentally, for 2018 the week numbers agree, though.

Selenium add weekdays to a date, weekend days not calculated correctly

I am running the below code on 6/7/2018 in order to omit weekends from any dates returned. However the code seems to determine the below days as the weekend.
13/7/2018 - Friday & 14/7/2018 - Saturday
rather than
14/7/2018 - Saturday & 15/7/2018 - Sunday
I am updating the field indicated to increase / reduce the amount of days in the future I want to select.
If I input 5 days the date returned is 12/7/2018 and if I input 6 days the date returned is 15/7/2018.
Is there something obvious I am missing, any help would be much appreciated.
Date date=new Date();
Calendar calendar = Calendar.getInstance();
date=calendar.getTime();
SimpleDateFormat s;
s=new SimpleDateFormat("dd/MM/yyyy");
System.out.println(s.format(date));
int days = 5; //I am updating this value to increase and decrease days
for(int i=0;i<days;)
{
calendar.add(Calendar.DAY_OF_MONTH, 1);
//here even sat and sun are added
//but at the end it goes to the correct week day.
//because i is only increased if it is week day
if(calendar.get(Calendar.DAY_OF_WEEK)<=5)
{
i++;
}
}
date=calendar.getTime();
s=new SimpleDateFormat("dd/MM/yyyy");
System.out.println(s.format(date));
DateTimeFormatter dateFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)
.withLocale(Locale.UK);
LocalDate date = LocalDate.now(ZoneId.of("Pacific/Truk"));
System.out.println(date.format(dateFormatter));
int days = 5;
int i = 0;
while (i < days) {
date = date.plusDays(1);
DayOfWeek day = date.getDayOfWeek();
if (! day.equals(DayOfWeek.SATURDAY) && ! day.equals(DayOfWeek.SUNDAY)) {
i++;
}
}
System.out.println(date.format(dateFormatter));
Output today (Sunday 8th July):
08/07/2018
13/07/2018
13th July is next Friday, so obviously it didn’t take Friday as weekend.
Is there something obvious I am missing(?)
It don’t think it’s that obvious: The Calendar class numbers the days of the week from 1 for Sunday through 7 for Saturday. This comes from an American understanding of weeks. So when your condition was that the day of week should be less than or equal to 5, you included Sunday (1) through Thursday (5) and filtered out Friday (6) and Saturday.
…if you could point me in the right direction to the documentation…
To find this information in the documentation you would have to look under each constant for day of week, SUNDAY, etc., and there follow the link Constant Field Values. See the links at the bottom of this answer.
The Calendar class has proved poorly designed (despite attempts to fix the problems with Date) and is now long outdated too. Instead I recommend that you use java.time, the modern Java date and time API. Which I of course do in the snippet above.
One of many problems with Calendar is the use of int for day of week (and other items that have names rather than being numbers). It’s unnatural and very easy to confuse. One may say that you reinforced the problem by comparing to 5 rather than to Calendar.FRIDAY, but because of the American numbering the latter wouldn’t have solved your issue either. java.time’s DayOfWeek is an enum and doesn’t invite for comparing using “less than” or “is before” (though you may, and it would work in your case). The code referring to named constants SATURDAY and SUNDAY is not only clearer to read, it is also less error-prone.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Documentation of LocalDate and DayOfWeek
Calendar.SUNDAYdocumentation
Constant Field Values documentation

Calling getTime changes Calendar value

I'm trying to get the sunday of the same week as a given date.
During this I ran into this problem:
Calendar calendar = Calendar.getInstance(Locale.GERMANY);
calendar.set(2017, 11, 11);
calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
System.out.println(calendar.getTime().toString());
results in "Sun Jan 07 11:18:42 CET 2018"
but
Calendar calendar2 = Calendar.getInstance(Locale.GERMANY);
calendar2.set(2017, 11, 11);
calendar2.getTime();
calendar2.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
System.out.println(calendar2.getTime().toString());
gives me the correct Date "Sun Dec 17 11:18:42 CET 2017"
Can someone explain why the first exmple is behaving this way? Is this really intended?
Thanks
Basically, the Calendar API is horrible, and should be avoided. It's not documented terribly clearly, but I think I see where it's going, and it's behaving as intended in this situation. By that I mean it's following the intention of the API authors, not the intention of you or anyone reading your code...
From the documentation:
The calendar field values can be set by calling the set methods. Any field values set in a Calendar will not be interpreted until it needs to calculate its time value (milliseconds from the Epoch) or values of the calendar fields. Calling the get, getTimeInMillis, getTime, add and roll involves such calculation.
And then:
When computing a date and time from the calendar fields, there may be insufficient information for the computation (such as only year and month with no day of month), or there may be inconsistent information (such as Tuesday, July 15, 1996 (Gregorian) -- July 15, 1996 is actually a Monday). Calendar will resolve calendar field values to determine the date and time in the following way.
If there is any conflict in calendar field values, Calendar gives priorities to calendar fields that have been set more recently. The following are the default combinations of the calendar fields. The most recent combination, as determined by the most recently set single field, will be used.
For the date fields:
YEAR + MONTH + DAY_OF_MONTH
YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
YEAR + DAY_OF_YEAR
YEAR + DAY_OF_WEEK + WEEK_OF_YEAR
In the first example, the fact that the last field set was "day of week" means it will then use the YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK calculation (I think). The year and month have been set to December 2017, but the week-of-month is the current week-of-month, which is the week 5 of January 2018... so when you then say to set the day of week to Sunday, it's finding the Sunday in the "week 5" of December 2017. December only had 4 weeks, so it's effectively rolling it forward... I think. It's all messy and you shouldn't have to think about that, basically.
In the second example, calling getTime() "locks in" the year/month/day you've specified, and computes the other fields. When you set the day of week, that's then adjusting it within the existing computed fields.
Basically, avoid this API as far as you possibly can. Use java.time, which is a far cleaner date/time API.
As Jon Skeet said, avoid Calendar. For your case it is truly horrible, and it’s poorly designed in general. Instead do
WeekFields weekFieldsForLocale = WeekFields.of(Locale.GERMANY);
// To find out which number Sunday has in the locale,
// grab any Sunday and get its weekFieldsForLocale.dayOfWeek()
int dayNumberOfSundayInLocale = LocalDate.now()
.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY))
.get(weekFieldsForLocale.dayOfWeek());
LocalDate date = LocalDate.of(2017, Month.DECEMBER, 11);
LocalDate sunday
= date.with(weekFieldsForLocale.dayOfWeek(), dayNumberOfSundayInLocale);
System.out.println(sunday);
This prints the expected date
2017-12-17
As others have already mentioned, the solution is to use java.time, the modern Java date and time API. Also generally it is so much nicer to work with. One nice feature is the LocalDate class that I am using. It is a date without time of day, which seems to match your requirements more precisely that Calendar did.
If the above looks complicated, it’s because, as I think you are aware, “Sunday of the same week” means different things in different locales. In the international standard that Germany follows, weeks begin on Monday, so Sunday is the last day of the week. In the American standard, for example, Sunday os the first day of the week. WeekFields.dayOfWeek() numbers the days of the week from 1 to 7, so when we want to set the day to Sunday, we first need to find out which number Sunday has got in this numbering (7 in Germany, 1 in the US). So for any Sunday, get its weekFieldsForLocale.dayOfWeek() value and later use this for setting the day of week to Sunday. The reason why this is necessary is that the with() method is so general and therefore has been designed to accept only numeric values; we can’t just pass it a DayOfWeek object.
If I substitute Locale.US into the code, I get 2017-12-10, which is the correct Sunday for a calendar where Sunday is the first day of the week. If you are sure your only want your code to work for Germany, you may of course just hardcode a 7 (please make it a constant with a very explanatory name).
Link: Oracle Tutorial Date Time explaining how to use java.time. There are other resources on the net (just avoid the outdated placed that suggest java.util.Calendar :-)

How should the "first month of each quarteryear" be represented using joda-time?

I'm working on some accounting logic. The logic is that an accounting that happened in the first month of a quarter year must have a value date that is at the end of the preceding quarter year. I know that I can represent the month as a period. But I have no idea how to represent the recurring period of a quarter year.
I'm able to do the calculation using joda-time classes that would give me the value date at the end of the preceding quarter year. However I would like to represent "first month of each quarter year" as a single value that I use in my calculations.
So is there some API in joda-time that is well suitable for representing this kind of recurring period?
Some example dates are:
date of invoce | value date
2013-01-01 | 2012-12-31
2013-01-31 | 2012-12-31
2013-02-01 | 2013-02-01
2013-03-31 | 2013-03-31
2013-04-01 | 2013-03-31
OK, here is more explanative example as requested in comments:
The accounting logic is about a kind of pension funds you have to apply for. You apply for the pensions of 2012 in the succeeding year, exactly on 1st of January 2013. It will be granted to you on the 15th of April 2013. Since April is the first month of the quarter year, the granting will have its value date set to the 31st of March. All pensions that are accounted within one quarter year are paid 1 month and 5 days after that quarter year has ended. So even if you have been granted your pension in April, you will still get it paid on 5th of May. Otherwise you would have to wait for it to be payed until 5th of September.
But I don't really know how this example should help. This question really is about modeling "every first month of each quarter year" with joda-time classes or even implementing some API of joda-time.
I had to implement this too. Here is an implementation that seems ok at first glance.
public class QuarterPeriods {
public static LocalDate quarterStartFor(LocalDate date) {
return date.withDayOfMonth(1).withMonthOfYear((((date.getMonthOfYear() - 1) / 3) * 3) + 1);
}
public static LocalDate quarterEndFor(LocalDate date) {
return quarterStartFor(date).plusMonths(3).minusDays(1);
}
}
public class QuarterPeriodsTest {
#Test
public void startOfQuarter() throws Exception {
assertThat(quarterStartFor(StubDates.dateOf("2011/02/02")), equalTo(StubDates.dateOf("2011/01/01")));
assertThat(quarterStartFor(StubDates.dateOf("2011/01/01")), equalTo(StubDates.dateOf("2011/01/01")));
assertThat(quarterStartFor(StubDates.dateOf("2011/02/02")), equalTo(StubDates.dateOf("2011/01/01")));
assertThat(quarterStartFor(StubDates.dateOf("2011/04/01")), equalTo(StubDates.dateOf("2011/04/01")));
assertThat(quarterStartFor(StubDates.dateOf("2011/07/01")), equalTo(StubDates.dateOf("2011/07/01")));
assertThat(quarterStartFor(StubDates.dateOf("2011/12/19")), equalTo(StubDates.dateOf("2011/10/01")));
}
#Test
public void endOfQuarter() throws Exception {
assertThat(quarterEndFor(StubDates.dateOf("2011/02/02")), equalTo(StubDates.dateOf("2011/03/31")));
assertThat(quarterEndFor(StubDates.dateOf("2011/01/01")), equalTo(StubDates.dateOf("2011/03/31")));
assertThat(quarterEndFor(StubDates.dateOf("2011/02/02")), equalTo(StubDates.dateOf("2011/03/31")));
assertThat(quarterEndFor(StubDates.dateOf("2011/04/01")), equalTo(StubDates.dateOf("2011/06/30")));
assertThat(quarterEndFor(StubDates.dateOf("2011/07/01")), equalTo(StubDates.dateOf("2011/09/30")));
assertThat(quarterEndFor(StubDates.dateOf("2011/12/19")), equalTo(StubDates.dateOf("2011/12/31")));
}
}
public class StubDates {
public static LocalDate dateOf(String date) {
return DateTimeFormat.forPattern("yyyy/MM/dd").withZone(DateTimeZone.UTC).parseDateTime(date).toLocalDate();
}
}
Algorithm
You need to write a routine where you pass in a date and get back a date representing the last day of previous quarter. Indeed, that sounds like a good name for the method, and a better summary of your problem: endingDateOfPreviousQuarter( someDate ).
Or alternatively named, in my own naming convention where I use start and stop to mean inclusive rather than exclusive boundary, stopDateOfPreviousQuarter( someDate ).
I would do that with a pair of methods.
startDateOfQuarter( someDate )
Extract the month of the passed date by calling monthOfYear().
Determine which quarter is that month (test for being between 1-3, 4-6, 7-9, 9-12).
Get start date of that quarter (as seen in code below, passing year & month & dayOfMonth to constructor).
stopDateOfPreviousQuarter( someDate )
Call "startDateOfQuarter" method, passing the date in question.
On the start date returned, call the Joda-Time method minusDays(1).
Voilà, you have the date of the last day in the previous quarter.
The main idea here is that generally it is better to find the beginning of a time element, and then use minus, rather than trying to directly get the ending point. Get the beginning of an hour, day, week, month, or quarter. This avoids problems with leap days, leap seconds†, Daylight Saving Time (DST), errors in remembering which months have 30 vs 31 days, and the problem of fractional seconds with varying resolution making it difficult to determine the very end of an hour or day. Furthermore, focusing on beginning of periods brings clarity to thinking about date-times, at least in my experience.
Info
ISO 8601 does not recognize quarters. Some people extend the spec to do so, using a "Q" combined with some identifier, as mentioned in this wiki.
Joda-Time 2 does not support quarters, as mentioned in this discussion in 2011.
ISO 8601 defines precisely a definition of 52 or 53 numbered weeks. Joda-Time supports that concept, asrepresented by the weekOfWeekYear. Some businesses define their quarters by a subset of that 1 to 52/53 range.
Or you could define your quarters by the end of the 3rd, 6th, 9th, and 12th months of the year. Joda-Time has constructors for DateTime class that lets you specify a month number. Note the use of the method withTimeAtStartOfDay() to let Joda-Time do the work of getting the first moment of the day as not all days in all time zones have a midnight.
org.joda.time.DateTimeZone parisDateTimeZone = org.joda.time.DateTimeZone.forID( "Europe/Paris" );
org.joda.time.DateTime q1Start = new org.joda.time.DateTime(2013, 1, 1, 0, 0, parisDateTimeZone ).withTimeAtStartOfDay();
org.joda.time.DateTime q2Start = new org.joda.time.DateTime(2013, 4, 1, 0, 0, parisDateTimeZone ).withTimeAtStartOfDay();
System.out.println( "Q1 begins in Paris FR: " + q1Start );
System.out.println( "Q2 begins in Paris FR: " + q2Start );
// When querying a database or comparing items in a collection to find Q1 data,
// Look for: (GreaterThanOrEqualTo q1Start) AND (LessThan q2Start)
If you absolutely want dates only without any time-of-day element, use the Joda-Time’s LocalDate class. That class sports a minusDays() method just like DateTime class.
By the way, consider whether you are dealing with simple dates (without times) or date-time. You may think, for example that invoices use only simple dates, but actually they are often stamped upon receipt with a clock machine that includes a time which may need to be recorded for legal and audit reasons. Also, usually databases store date values as date-time based in UTC (with no time zone offset).
† Joda-Time ignores leap-seconds, but my point still stands.

Categories

Resources