Momentjs calendar() equivalent for Java - java

Momentjs has the calendar() function to pretty print timespans like below.
For example:
"Last Monday at 1:14 PM"
"09/21/2017" (if the date is a while ago)
Is there an equivalent function in Java (Joda-Time if possible)?
moment().subtract(10, 'days').calendar(); // 09/21/2017
moment().subtract(6, 'days').calendar(); // Last Monday at 1:14 PM
moment().subtract(3, 'days').calendar(); // Last Thursday at 1:14 PM
moment().subtract(1, 'days').calendar(); // Yesterday at 1:14 PM
moment().calendar(); // Today at 1:14 PM
moment().add(1, 'days').calendar(); // Tomorrow at 1:14 PM
moment().add(3, 'days').calendar(); // Wednesday at 1:14 PM
moment().add(10, 'days').calendar(); // 10/11/2017

java.time
Modern approach uses the industry-leading java.time classes.
ZoneId z = ZoneId.now( “America/Montreal” ) ;
LocalDate today = LocalDate.now( z ) ;
Use the plus and minus methods to do math.
LocalDate tomorrow = today.plusDays( 1 ) ;
Search Stack Overflow. Nearly every basic date-time Question has already been asked an answered.
Strings
The java.time classes do not generate strings such as “tomorrow” and “Last Monday”. So no direct equivalent of your referenced library. You will have to do the peasant work yourself.
Search for the DateTimeFormatter class, and the DateTimeFormatterBuilder class.
Also, the DayOfWeek enum and its auto-localizing getDisplayName method may be useful.
prettytime
The prettytime library may help you, though I’ve not used it.
Joda-Time
The Joda-Time project is in maintenance mode. The team advises migration to the java.time 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.
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.

There's no built-in function for that in Java, but it's not so hard to do it with the existing API's. First you need to get the difference from today (in days), and choose the proper string based on moment.js rules:
Last week Last Monday at 2:30 AM
The day before Yesterday at 2:30 AM
The same day Today at 2:30 AM
The next day Tomorrow at 2:30 AM
The next week Sunday at 2:30 AM
Everything else 7/10/2011
In Joda-Time, you can use the org.joda.time.Days class to get the difference in days. One detail is that I'm considering just the date (day/month/year) and ignoring the time (hour/minute/second) to get the difference (but you can adjust it to your needs). The method will be like this:
public String calendar(DateTime dt) {
StringBuilder sb = new StringBuilder();
// check difference in days from today, considering just the date (ignoring the hours)
int days = Days.daysBetween(new LocalDate(), dt.toLocalDate()).getDays();
if (days == 0) { // today
sb.append("Today ");
} else if (days == 1) { // tomorrow
sb.append("Tomorrow ");
} else if (days == -1) { // yesterday
sb.append("Yesterday ");
} else if (days > 0 && days < 7) { // next week
sb.append(dt.dayOfWeek().getAsText(Locale.ENGLISH)).append(" ");
} else if (days < 0 && days > -7) { // last week
sb.append("Last ").append(dt.dayOfWeek().getAsText(Locale.ENGLISH)).append(" ");
}
if (Math.abs(days) < 7) { // difference is less than a week, append current time
sb.append("at ").append(dt.toString("h:mm a", Locale.ENGLISH));
} else { // more than a week of difference
sb.append(dt.toString("M/d/yyyy"));
}
return sb.toString();
}
I'm using a org.joda.time.LocalDate to get the difference, so the time will be ignored (if you use a DateTime instead, the difference is only 1 day if it has passed more than 24 hours, so change the code according to what you need).
I also used Math.abs(days) < 7 to consider if the difference is more than a week, but I'm not sure if moment.js considers <= 7.
Anyway, some examples of usage:
DateTime now = new DateTime();
System.out.println(calendar(now.minusDays(10))); // 9/22/2017
System.out.println(calendar(now.minusDays(6))); // Last Tuesday at 9:34 AM
System.out.println(calendar(now.minusDays(3))); // Last Friday at 9:34 AM
System.out.println(calendar(now.minusDays(1))); // Yesterday at 9:34 AM
System.out.println(calendar(now)); // Today at 9:34 AM
System.out.println(calendar(now.plusDays(1))); // Tomorrow at 9:34 AM
System.out.println(calendar(now.plusDays(3))); // Thursday at 9:34 AM
System.out.println(calendar(now.plusDays(10))); // 10/12/2017
The output is (considering that today is October 2nd 2017, and I ran the code at 9:34 AM in my local time):
9/22/2017
Last Tuesday at 9:34 AM
Last Friday at 9:34 AM
Yesterday at 9:34 AM
Today at 9:34 AM
Tomorrow at 9:34 AM
Thursday at 9:34 AM
10/12/2017
You can also modify the method to take a reference date to compare with (instead of using a hardcoded new LocalDate() inside the method).
Java new Date/Time API
Joda-Time is in maintainance mode and is being replaced by the new APIs, so I don't recommend start a new project with it. Even in joda's website it says: "Note that Joda-Time is considered to be a largely “finished” project. No major enhancements are planned. If using Java SE 8, please migrate to java.time (JSR-310).".
If you're using Java 8, consider using the new java.time API. It's easier, less bugged and less error-prone than the old APIs.
If you're using Java 6 or 7, you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, you'll also need the ThreeTenABP (more on how to use it here).
The code below works for both.
The only difference is the package names (in Java 8 is java.time and in ThreeTen Backport (or Android's ThreeTenABP) is org.threeten.bp), but the classes and methods names are the same.
This API is very similar to Joda-Time, so the code has minor differences:
static DateTimeFormatter HOUR_FORMAT = DateTimeFormatter.ofPattern("h:mm a", Locale.ENGLISH);
static DateTimeFormatter MDY_FORMAT = DateTimeFormatter.ofPattern("M/d/yyyy");
public String calendar(ZonedDateTime dt) {
StringBuilder sb = new StringBuilder();
// check difference in days from today, considering just the date (ignoring the hours)
long days = ChronoUnit.DAYS.between(LocalDate.now(), dt.toLocalDate());
if (days == 0) { // today
sb.append("Today ");
} else if (days == 1) { // tomorrow
sb.append("Tomorrow ");
} else if (days == -1) { // yesterday
sb.append("Yesterday ");
} else if (days > 0 && days < 7) { // next week
sb.append(dt.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.ENGLISH)).append(" ");
} else if (days < 0 && days > -7) { // last week
sb.append("Last ").append(dt.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.ENGLISH)).append(" ");
}
if (Math.abs(days) < 7) { // difference is less than a week, append current time
sb.append("at ").append(dt.format(HOUR_FORMAT));
} else { // more than a week of difference
sb.append(dt.format(MDY_FORMAT));
}
return sb.toString();
}
I used a ZonedDateTime, which is an equivalent of Joda's DateTime (it represents a date and time in a timezone).
When calling DAYS.between, I converted it to a LocalDate, so the comparison considers only the date (day/month/year). If I used a ZonedDateTime instead, the time would also be considered, so the result would be 1 day only if it has passed more than 24 hours (so you can change it according to your needs).
Note that I also had to create 2 instances of DateTimeFormatter. I created them outside of the method, so they can be reused (no need to create them all the time inside the method). Joda-Time didn't need it because the toString method in Joda's objects can take a pattern and internally creates a formatter, while in java.time API you must create the formatter explicity.
Using it is also similar to Joda-Time:
ZonedDateTime now = ZonedDateTime.now();
System.out.println(calendar(now.minusDays(10))); // 9/22/2017
System.out.println(calendar(now.minusDays(6))); // Last Tuesday at 9:34 AM
System.out.println(calendar(now.minusDays(3))); // Last Friday at 9:34 AM
System.out.println(calendar(now.minusDays(1))); // Yesterday at 9:34 AM
System.out.println(calendar(now)); // Today at 9:34 AM
System.out.println(calendar(now.plusDays(1))); // Tomorrow at 9:34 AM
System.out.println(calendar(now.plusDays(3))); // Thursday at 9:34 AM
System.out.println(calendar(now.plusDays(10))); // 10/12/2017
Just a note about timezones. In java.time API, all the date classes has a no-arg now() method that gets the current date/time in the JVM's default timezone.
Although it's very conveninent, it also has some drawbacks, because the default timezone can be changed without notice, even at runtime. It's better to specify which timezone you want, if possible.
The API uses IANA timezones names (always in the format Region/City, like America/New_York or Europe/Paris).
Avoid using the 3-letter abbreviations (like CET or EST) because they are ambiguous and not standard.
You can get a list of available timezones (and choose the one that fits best your system) by calling ZoneId.getAvailableZoneIds().
To get the current date/time in a specific timezone, use the ZoneId class:
// get the current date/time in a specific timezone
ZonedDateTime.now(ZoneId.of("Europe/Paris"));

Related

Java current date minus 3 months and start from month begining [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I need to get statistics for a quarter.
Example: today is February 10th 2018, I need to retrieve data from December 2017, from 1st to 31st, then from January 2018, from 1st to 30th and from February 1st to current date.
How can I achieve this using Java Date?
tl;dr
YearMonth.now().minusMonths( 1 ).atEndOfMonth() // or .atDay( 1 )
Details
Get today’s date.
ZoneId z = ZoneId.of( “Africa/Tunis” ) ;
LocalDate today = LocalDate.now( z ) ;
Get the year-month of that date.
YearMonth ymCurrent = YearMonth.from( today ) ;
Add the ThreeTen-Extra library to your project to access the LocalDateRange class. This class represents as one object a pair of LocalDate objects, start date and stop date, for a date range from one date to the other date.
LocalDateRange rangeCurrent = LocalDateRange.ofClosed( ymCurrent.atDay( 1 ) , today ) ;
Move to previous month.
YearMonth ymPrevious = ymCurrent.minusMonths( 1 ) ;
LocalDateRange rangePrevious = LocalDateRange.ofClosed( ymPrevious.atDay( 1 ) , ymPrevious.atEndOfMonth() ) ;
Subtract yet another time for your third month.
Tip: Consider using the Half-Open approach to defining a span of time, where the beginning is inclusive while the ending is exclusive. So a month starts with the first day of the month and runs up to, but does not include, the first day of the following month.
For another valid approach using java.time classes, see the Answer by diston.
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.
Try something like this:
// Get current date
Calendar start;
start = Calendar.getInstance();
// Go to beginning of month
start.set(Calendar.DAY_OF_MONTH, 1);
start.set(Calendar.HOUR_OF_DAY, 0);
start.set(Calendar.MINUTE, 0);
start.set(Calendar.SECOND, 0);
start.set(Calendar.MILLISECOND, 0);
// Go 2 months back
my_date.add(Calendar.MONTH, -2);
// Get end of same month
Calendar end;
end = start.clone();
end.add(Calendar.MONTH, 1);
end.add(Calendar.DAY_OF_MONTH, -1);
Then, do something similar for the other months
You can use Java 8's java.time classes (or threeten backport for Java <= 7).
If you'll work only with day/month/year and don't care about hours and timezones, the best class to use is LocalDate. To create a specific date is easy:
// February 10th 2018
LocalDate current = LocalDate.of(2018, 2, 10);
Or you can call LocalDate.now() to get the current date.
Then, to get to December 1st 2017, you must subtract 2 months (2 months before February is December) and set the day to 1:
// start is December 1st 2017
LocalDate start = current
// 2 months ago = December
.minusMonths(2)
// change day of month to 1st
.withDayOfMonth(1);
Then you can loop from December 1st to February 10th:
LocalDate date = start;
while (date.isBefore(current)) {
// do whatever you need with the date
// go to the next day
date = date.plusDays(1);
}
Note that plusDays returns a new object, so I must assign it to the same variable, otherwise it won't be changed.
I also used isBefore, which doesn't include the current date in the loop - it'll stop at February 9th. If you want to include February 10th, change the condition to if (! date.isAfter(current))

AlarmManger doesn't work [duplicate]

This question already has answers here:
Why is January month 0 in Java Calendar?
(18 answers)
Closed 2 years ago.
Calendar rightNow = Calendar.getInstance();
String month = String.valueOf(rightNow.get(Calendar.MONTH));
After the execution of the above snippet, month gets a value of 10 instead of 11. How come?
Months are indexed from 0 not 1 so 10 is November and 11 will be December.
They start from 0 - check the docs
As is clear by the many answers: the month starts with 0.
Here's a tip: you should be using SimpleDateFormat to get the String-representation of the month:
Calendar rightNow = Calendar.getInstance();
java.text.SimpleDateFormat df1 = new java.text.SimpleDateFormat("MM");
java.text.SimpleDateFormat df2 = new java.text.SimpleDateFormat("MMM");
java.text.SimpleDateFormat df3 = new java.text.SimpleDateFormat("MMMM");
System.out.println(df1.format(rightNow.getTime()));
System.out.println(df2.format(rightNow.getTime()));
System.out.println(df3.format(rightNow.getTime()));
Output:
11
Nov
November
Note: the output may vary, it is Locale-specific.
As several people have pointed out, months returned by the Calendar and Date classes in Java are indexed from 0 instead of 1. So 0 is January, and the current month, November, is 10.
You might wonder why this is the case. The origins lie with the POSIX standard functions ctime, gmtime and localtime, which accept or return a time_t structure with the following fields (from man 3 ctime):
int tm_mday; /* day of month (1 - 31) */
int tm_mon; /* month of year (0 - 11) */
int tm_year; /* year - 1900 */
This API was copied pretty much exactly into the Java Date class in Java 1.0, and from there mostly intact into the Calendar class in Java 1.1. Sun fixed the most glaring problem when they introduced Calendar – the fact that the year 2001 in the Gregorian calendar was represented by the value 101 in their Date class. But I'm not sure why they didn't change the day and month values to at least both be consistent in their indexing, either from zero or one. This inconsistency and related confusion still exists in Java (and C) to this day.
Months start from zero, like indexes for lists.
Therefore Jan = 0, Feb = 1, etc.
From the API:
The first month of the year is JANUARY
which is 0; the last depends on the
number of months in a year.
http://java.sun.com/j2se/1.5.0/docs/api/java/util/Calendar.html
tl;dr
LocalDate.now() // Returns a date-only `LocalDate` object for the current month of the JVM’s current default time zone.
.getMonthValue() // Returns 1-12 for January-December.
Details
Other answers are correct but outdated.
The troublesome old date-time classes had many poor design choices and flaws. One was the zero-based counting of month numbers 0-11 rather than the obvious 1-12.
java.time
The java.time framework is built into Java 8 and later. These classes supplant the old troublesome date-time classes such as java.util.Date, .Calendar, & java.text.SimpleDateFormat.
Now in maintenance mode, the Joda-Time project also advises migration to java.time.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations.
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP.
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time.
Months 1-12
In java.time the month number is indeed the expected 1-12 for January-December.
The LocalDate class represents a date-only value without time-of-day and without time zone.
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(!).
LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) );
int month = today.getMonthValue(); // Returns 1-12 as values.
If you want a date-time for a time zone, use ZonedDateTime object in the same way.
ZonedDateTime now = ZonedDateTime.now( ZoneId.of( "America/Montreal" ) );
int month = now.getMonthValue(); // Returns 1-12 as values.
Convert legacy classes
If you have a GregorianCalendar object in hand, convert to ZonedDateTime using new toZonedDateTime method added to the old class. For more conversion info, see Convert java.util.Date to what “java.time” type?
ZonedDateTime zdt = myGregorianCalendar.toZonedDateTime();
int month = zdt.getMonthValue(); // Returns 1-12 as values.
Month enum
The java.time classes include the handy Month enum, by the way. Use instances of this class in your code rather than mere integers to make your code more self-documenting, provide type-safety, and ensure valid values.
Month month = today.getMonth(); // Returns an instant of `Month` rather than integer.
The Month enum offers useful methods such as generating a String with the localized name of the month.
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.
cal.get(Calendar.MONTH) + 1;
The above statement gives the exact number of the month. As get(Calendar.Month) returns month starting from 0, adding 1 to the result would give the correct output. And keep in mind to subtract 1 when setting the month.
cal.set(Calendar.MONTH, (8 - 1));
Or use the constant variables provided.
cal.set(Calendar.MONTH, Calendar.AUGUST);
It would be better to use
Calendar.JANUARY
which is zero ...

Java, set date to 0/0/0

I have an object with some dates and I'd like to return them in the getter. The problem is that i need to do Date.toString(); because I have to print them, and when the date is null I get a NullPointerException.
I was thinking about returning the date 0/0/0 when the date is null, but I don't know how to set this value. Is there any way? Just like new Date(0) returns the 1970-01-01-00:00:00, is there anything similar to this but to return 0/0/0?
Thanks!
There is no Date 0/0/0, by definition, as there is no Day 0 and no Month 0. A day is a member of the set {1,..,28 or 30 or 31} and month is a member of the set {1,...12}. Hence, it is impossible - and it is good that it is impossible - to express 0/0/0 as Date Object.
The terrible Date and Calendar classes were supplanted years ago by the java.time classes.
LocalDate
The LocalDate class represents a date-only value without time-of-day and without time zone or offset-from-UTC.
You may set the month by a number, with sane numbering 1-12 for January-December.
LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ; // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.
Or, better, use the Month enum objects pre-defined, one for each month of the year. Tip: Use these Month objects throughout your codebase rather than a mere integer number to make your code more self-documenting, ensure valid values, and provide type-safety. Ditto for Year & YearMonth.
LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;
Zero-date senseless
is there anything similar to this but to return 0/0/0?
No.
Trying to represent a null with a date of all zeros is the wrong way to go. There is no such thing as a date of all zeros (year, month, and day all being zero).
Instead, pick an arbitrary date to use as a special value. Document thoroughly your choice and its meaning.
Do not choose a date too distant in time. Many libraries and databases are limited in their range of values. You do not want your data to break there.
Generally I would suggest using the epoch of 1970-01-01T00:00:00Z, the first moment of 1970 in UTC (the Z means UTC, and is pronounced “Zulu”). This moment is used as the epoch reference for Unix, the legacy date-time classes bundled with Java, and the modern date-time classes built into Java 8 and later. So many programmers and sysadmins will recognize this moment as special. The java.time classes include a constant for your convenience: Instant.EPOCH.
Obviously my suggestion applies to common business-oriented apps interested in forward-looking near dates, with past history not reaching back to 1970. If that does not meet your needs, pick another arbitrary value, such as 1900-01-01.
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.
Java uses the Gregorian Calendar which has no 0 year. Also, you have to keep in mind that there is now zero month either. Setting a month to '0' would result in getting January, as the months are based on 0-index. Zero day does not exist either.
Assuming that you are getting and returning "modern" dates (AD), you could set your "lower bound" date in BC era. So, when you get a null date you could return a BC date to differentiate it from your actual ones. Here's the code:
Calendar cal = Calendar.getInstance();
cal.set(Calendar.ERA, GregorianCalendar.BC); //Set the BC era
cal.set(Calendar.YEAR, 1); //Set the year to 1 BC
cal.set(Calendar.MONTH, 0); //Set the month to January
cal.set(Calendar.DAY_OF_MONTH, 1); //Set the day to 1st
DateFormat df = new SimpleDateFormat("yyyy MMM d G"); //Format the date
String returnedDate = df.format(cal.getTime()); //Generate a String of it for other use
You could customize the code to your needs if you are also getting dates from BC era (maybe by setting an even older date).
EDIT: Of course you could use what the others have suggested, namely checking for null and returning a "0/0/0" String but this may cause further problems later on, when you will try to parse the aforementioned String. Also, due to the fact that by definition 0/0/0 is not a valid date in the Gregorian Calendar (see clarification), you should avoid using this "wildcard" String and set an actual date, as I detailed above.
CLARIFICATION: The Gregorian Calendar does not contain neither a 0 year nor a 0 month or 0 day by definition and not by implementation in Java (meaning it's not an intentional limitation, it's part of its concept).
Class: LocalDate
Package: Threetenabp
My solution was to create LocalDate constants using the EPOCH date as basis with LocalDate.ofEpochDay(). And instead of returning a null date (that does not exist) I return a LocalDate object according to the case evaluated. Then depending on what I get back the getBirthdate method in my domain I do something.
Definition of constants
public class LocalDateUtils {
public static final LocalDate EMPTY_FIELDS = createLocalDate(0);
public static final LocalDate EMPTY_FIELD_DAY_OF_MONTH = createLocalDate(1);
public static final LocalDate EMPTY_FIELD_MONTH = createLocalDate(2);
public static final LocalDate EMPTY_FIELD_YEAR = createLocalDate(3);
/**
* Purpose: Create a date with #param epochDay days added
* Observation: EPOCH (1970-01-01)
*/
private static LocalDate createLocalDate(long epochDay) {
return LocalDate.ofEpochDay(epochDay);
}
}
Implementation
/**
* Purpose: Describe a birthday or a constant indicating empty field (s).
* Observation: According to if the parameters are zeros.
*/
LocalDate getBirthdate(int year,
int month,
int dayOfMonth) {
if (dayOfMonth == 0 && month == 0 && year == 0)
return LocalDateUtils.EMPTY_FIELDS;
if (dayOfMonth == 0)
return LocalDateUtils.EMPTY_FIELD_DAY_OF_MONTH;
if (month == 0)
return LocalDateUtils.EMPTY_FIELD_MONTH;
if (year == 0)
return LocalDateUtils.EMPTY_FIELD_YEAR;
return LocalDate.of(year, month, dayOfMonth);
}
Usage
if (getBirthdate() == LocalDateUtils.EMPTY_FIELDS) {
}
if (getBirthdate() == LocalDateUtils.EMPTY_FIELD_DAY_OF_MONTH) {
}
if (getBirthdate() == LocalDateUtils.EMPTY_FIELD_MONTH) {
}
if (getBirthdate() == LocalDateUtils.EMPTY_FIELD_YEAR) {
}
Source
GL
This simple approach can get you what you need, as already mentioned in the comments to your question:
public String dateString(Date date) {
if (date != null)
return date.toString();
else
return "0/0/0";
}
or
String dateString;
try {
dateString = date.toString();
}
catch(NullPointerException e) {
dateString = "0/0/0";
}
Update: the second alternative is discouraged as suggested in the comments.

Check if the Calendar date is a sunday

I am trying to figure out how to make my program count the number of Sundays in a week.
I have tried the following thing:
if (date.DAY_OF_WEEK == date.SUNDAY) {
System.out.println("Sunday!");
}
Yet it does not seem to work?
When I try to System.out.Println the date.DAY_OF_WEEK I get: 7
Does anyone know how I can check if the current calendar date is Sunday?
UPDATE FOR MORE INFORMATION
firt of all the date.DAY_OF_WEEK is a Calendar object!
i made sure to set the Calendar object date to a sunday
The system out print where i get 7 is what it returns to me when i try to run date.DAY_OF_MONTH even if the day it set to a sunday
2nd UPDATE TO ALEX
This is more or less my code
Calendar startDate = Calendar.getInstance();
startDate.set(2012, 12, 02);
if (startDate.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
System.out.println("true");
}else {
System.out.println("FALSE");
}
Calendar cal = ...;
if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
System.out.println("Sunday!");
}
Calendar.DAY_OF_WEEK always equals to 7 no matter what instance of Calendar you are using (see this link), it is a constant created to be used with the Calendar.get() method to retrieve the correct value.
It is the call to Calendar.get(Calendar.DAY_OF_WEEK) that will return the real day of week. Besides, you will find useful values in the Calendar class like Calendar.SUNDAY (and the other days and months) in order for you to be more explicit in your code and avoid errors like JANUARY being equal to 0.
Edit
Like I said, the Calendar class does contains useful constants for you to use. There is no month number 12 they start at 0 (see above), so DECEMBER is month number 11 in the Java Date handling.
Calendar startDate = Calendar.getInstance();
startDate.set(2012, Calendar.DECEMBER, 02);
if (startDate.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
System.out.println("true");
} else {
System.out.println("FALSE");
}
Will print true of course.
Note: the Joda-Time project is now in maintenance mode. See this answer if you don't have to work with legacy code.
If you have to work with date or time a lot, you might want to try using Joda-Time.
Your code would look something like this:
LocalDate startDate = new LocalDate(2012, 12, 2);
int day = startDate.dayOfWeek().get(); // gets the day of the week as integer
if (DateTimeConstants.SUNDAY == day) {
System.out.println("It's a Sunday!");
}
You can also get a text string from dayOfWeek():
String dayText = startDate.dayOfWeek().getAsText();
will return the string "Sunday".
tl;dr
boolean todayIsSunday = LocalDate.now( ZoneId.of( "America/Montreal" ) ).getDayOfWeek().equals( DayOfWeek.SUNDAY ) ;
java.time
The other Answers are outdated. The modern approach uses java.time classes.
LocalDate
The LocalDate class represents a date-only value without time-of-day and without time zone or offset-from-UTC.
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.
If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment during runtime(!), so your results may vary. Better to specify your desired/expected time zone explicitly as an argument. If critical, confirm the zone with your user.
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/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the code becomes ambiguous to read in that we do not know for certain if you intended to use the default or if you, like so many programmers, were unaware of the issue.
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
Or specify a date. You may set the month by a number, with sane numbering 1-12 for January-December.
LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ; // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.
Or, better, use the Month enum objects pre-defined, one for each month of the year. Tip: Use these Month objects throughout your codebase rather than a mere integer number to make your code more self-documenting, ensure valid values, and provide type-safety. Ditto for Year & YearMonth.
LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;
DayOfWeek
For any LocalDate, you can obtain its day-of-week as a DayOfWeek object. The DayOfWeek enum automatically instantiates seven objects, one for each day of the week.
boolean isSunday = ld.getDayOfWeek().equals( DayOfWeek.SUNDAY ) ;
One Sunday per week
count the number of Sundays in a week.
That would be 1, always one Sunday per week.
If your goal is finding the next Sunday, use a TemporalAdjuster defined in TemporalAdjusters class.
TemporalAdjuster ta = TemporalAdjusters.nextOrSame( DayOfWeek.SUNDAY ) ;
LocalDate nextOrSameSunday = ld.with( ta ) ;
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. Hibernate 5 & JPA 2.2 support java.time.
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 brought 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 (26+) bundle implementations of the java.time classes.
For earlier Android (<26), a process known as API desugaring brings a subset of the java.time functionality not originally built into Android.
If the desugaring does not offer what you need, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above) to Android. See How to use ThreeTenABP….

java get day of week is not accurate

I am trying to determine what day of the week is the first day of the month but for some reason it is not returning me the correct day of the week.
Here is my code below:
CalendarMonth[] months = CalendarUtils.constructMonthViewArray(new GregorianCalendar());
public static CalendarMonth[] constructMonthViewArray(Calendar cal) {
CalendarMonth[] months = new CalendarMonth[CALENDAR_GRID_SIZE];
int year = cal.get(cal.YEAR);
int month = cal.get(cal.MONTH);;
// calculate how many days in the month
int numOfDays = getNumOfDaysInMonth(cal);
// calculate what day(mon-sunday) is the 1st of the month
int firstDayOfMonth = getFirstDayOfMonth(cal);
private static int getFirstDayOfMonth(Calendar cal) {
int firstDay = cal.get(Calendar.DAY_OF_WEEK);
Log.d(TAG, "");
// decrement it because our array deals with values 0-6(indexes)
firstDay--;
if (firstDay == 0) {
firstDay = 6;
} else {
// decrement again so that the days start from 0.
firstDay--;
}
return firstDay;
}
The line from "int firstDay = cal.get(Calendar.DAY_OF_WEEK);" fails to give me the correct day of the week and returns the value 2 for getting the 1st day of this month(January 2011) when the first of the month was on a Saturday(7).
Am I missing something? I have debugged and checked what month, year and date the cal variable is set and it indeed indicated today's date as corrected but when i get the day of week it doesn't get the value 7.
I can't reproduce the problem you're seeing. As Michael says, there's a lot of code you haven't shown us, but Calendar.getDayOfWeek definitely works:
import java.util.*;
public class Test {
public static void main(String[] args) {
Calendar calendar = new GregorianCalendar();
calendar.set(2011, 0, 1); // 0 = January
System.out.println(calendar.get(Calendar.DAY_OF_WEEK)); // Prints 7
}
}
Did you maybe forget that months are 0-based in java.util.Calendar?
If you can produce a similar short but complete program which shows the wrong day of the week, please post it.
The fact that you're decrementing firstDay twice within getFirstDayOfMonth seems somewhat odd, as well as the fact that it doesn't really reflect the name of the method (as Michael mentioned).
Finally, my constant recommendation for Java date/time handling: if you can possibly use Joda Time instead of java.util.Calendar, do so. It's a much, much better API.
The code of getFirstDayOfMonth() appears not to do what the method name says at all - but to actually understand what is happening, we need to see all the code that is involved, especially how the calendar initialized and the code of getNumOfDaysInMonth()
One thing to keep in mind: what is considered the first day of the week depends on the locale, as per getFirstDayOfWeek()
tl;dr
Convert from terrible legacy classes (Calendar, GregorianCalendar, etc.) to modern java.time classes (ZonedDateTime, LocalDate, etc.). Then get object for day-of-week, and ask it to automatically localize the name of that day of the week.
(GregorianCalendar) myJavaUtilCalendar // Cast your `Calendar` to `GregorianCalendar` assuming it actually is one.
.toZonedDateTime() // Convert from legacy class to modern class.
.toLocalDate() // Extract date-only object, without time-of-day and without time zone.
.with( // Adjust to another date by calling `TemporalAdjuster` implementation such as are found in `TemporalAdjusters` class.
TemporalAdjusters.firstDayOfMonth() // Adjust to the first day of the month.
) // Returns another `LocalDate` object, for the first of the month.
.getDayOfWeek() // Obtain a `DayOfWeek` enum object, one of seven pre-defined objects representing each day of the week.
.getDisplayName( // Automatically localize.
TextStyle.FULL , // Specify how long or abbreviated.
Locale.CANADA_FRENCH // Or `Locale.US` etc. to specify the human language and cultural norms to use in localizing.
) // Returns text in a `String` such as “Monday” or “lundi”.
java.time
The java.util.Calendar/.Date and related classes are a confusing mess as you have learned the hard way.
The modern approach uses java.time classes.
Conversion
If starting with a java.util.Calendar object, convert to java.time.
An Instant is a moment on the timeline in UTC.
Instant instant = myJavaUtilCalendarObject.toInstant();
Apply a time zone in order to get a date in order to get a day-of-week.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( zoneId );
Note that a time zone is critical in determining a date (and therefore day-of-week). "Today" is not the same date everywhere in the world simultaneously. A new day dawns earlier, for example, in Paris than in Montréal.
First Day Of Month
Let's move to the first of the month by calling withDayOfMonth.
ZonedDateTime zdtFirstOfMonth = zdt.withDayOfMonth(1);
Note that moving a date-time to first of month has issues. Anomalies such as Daylight Saving Time (DST) could have a surprising effect. Read the doc so you understand the behavior.
DayOfWeek
For day of week, use the well-named DayOfWeek enum.
DayOfWeek dayOfWeek = zdtFirstOfMonth.getDayOfWeek();
I suggest passing instances of this enum rather than a magic number like 2, 7, etc. But if you insist, you can extract an integer.
int dayOfWeekNumber = dayOfWeek.getValue();
To get a String of the name of day-of-week, let java.time generate a localized String via the getDisplayName method.
String output = dayOfWeek.getDisplayName( TextStyle.FULL , Locale.CANADA_FRENCH ); // Or Locale.ENGLISH
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.

Categories