I am working on a learning project related to Android. I am trying to get current year & month by using below code but it not works for me.
GregorianCalendar gc = new GregorianCalendar();
gc.YEAR // returning 1
gc.MONTH // returning 2
Calendar c = Calendar.getInstance();
c.YEAR // returning 1
c.MONTH // returning 2
Can someone help me? Am i doing something wrong? please forgive me i am new to java development. thanks.
Just to give a bit more background:
Both new GregorianCalendar() and Calendar.getInstance() will correctly give a calendar initialized at the current date and time.
MONTH and YEAR are constants within the Calendar class. You should not use them "via" a reference which makes it look like they're part of the state of an object. It's an unfortunate part of the design of the Calendar class that to access the values of different fields, you need to call get with a field number, specified as one of those constants, as shown in other answers:
Calendar c = Calendar.getInstance();
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH);
Note that the month numbers are 0-based, so at the time of this writing (in April) the month number will be 3.
It's an unfortunate part of the design of the Java language that you can reference static members (such as constants) via expressions of that type, rather than only through the type name.
My recommendations:
If your IDE allows it (as Eclipse does), make expressions such as c.YEAR give a compile-time error - you'll end up with much clearer code if you always use Calendar.YEAR.
Where possible, use Joda Time - a much better date/time library for Java. Admittedly on Android you may be a bit space-constrained, but if your app does a lot of date/time manipulation, it would save you a lot of headaches.
Note MONTHS starts from 0..So if you need to map it to practical problems just add +1
int month=c.get(Calendar.MONTH)+1;
int year=c.get(Calendar.YEAR);
int month=c.get(Calendar.MONTH);
System.out.println(year);
System.out.println(month);
tl;dr
YearMonth.now(
ZoneId.of( "America/Montreal" )
)
Details
The Answer by Jon Skeet is correct. You were accessing constants rather than interrogating your own object.
Here is an entirely different alternative, using modern date-time classes.
Avoid legacy date-time classes
The old date-time classes such as java.util.Date, java.util.Calendar, and java.text.SimpleTextFormat are now legacy, supplanted by the java.time classes.
YearMonth
If you are focused on the year and month without a date, without a time-of-day, and without a time zone, use the YearMonth class.
Rather than pass mere integer numbers around for year and for month, pass around objects of this class. Doing so provides type-safety, ensures valid values, and makes your code more self-documenting.
Determining the current year and month means determining the current date. And for that a time zone is crucial. For any given moment, the date varies around the globe by zone.
ZoneId z = ZoneId.of( "America/Montreal" );
YearMonth ym = YearMonth.now( z );
You can interrogate for its parts.
int year = ym.getYear();
int month = ym.getMonthValue();
This class offers handy methods such as telling you if this is a leap year. You can do math, such as adding/subtracting months/years. You can get a date for any day of this year-month. And more.
Month
Rather than mess around with a mere integer for month, I suggest you use the Month enum. This class has a dozen instances pre-defined, one for each month of the year. As mentioned above, using objects gives you type-safety, valid values, and self-documenting code.
Month m = ym.getMonth();
The class has helpful methods such as generating an localized string with the month’s name.
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 and SE 9 and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use….
Calendar c= Calendar.getInstance()
int cyear = c.get(Calendar.YEAR);//calender year starts from 1900 so you must add 1900 to the value recevie.i.e., 1990+112 = 2012
int cmonth = c.get(Calendar.MONTH);//this is april so you will receive 3 instead of 4.
int cday = c.get(Calendar.DAY_OF_MONTH);
refer this LINK
How to get current Year and Month.
Calendar calendar = Calendar.getInstance();
int month = calendar.get(Calendar.MONTH) + 1;
int year = calendar.get(Calendar.YEAR);
Very important to add 1 to get the correct month, because the first month value is 0:
int month = calendar.get(Calendar.MONTH) + 1;
MONTH :Field number for get and set indicating the month. This is a calendar-specific value. The first month of the year in the Gregorian and Julian calendars is JANUARY which is 0; the last depends on the number of months in a year.
Related
setting the day field in a calendar using
myCalender.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY);
does is put set the day to the next Friday or the past Friday or maybe the closest?
Also what if I don't set the year or any other field for the calendar, what are the default values?
Neither. Yet. It’s complicated. But don’t use Calendar, see below.
From the documentation of the two-arg set method:
Sets the given calendar field to the given value. The value is not
interpreted by this method…
So during this call it just sets the day-of-week field to Friday. The year, month and day-of-month stay the same, that is, the date isn’t effectively changed. Yet.
If and when the Calendar eventually computes and resolves its fields,
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.
If you have only set the day of week (which will likely have introduced a conflict with the other fields), the following combination applies:
YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
So it will pick the Friday in the same week.
What defines a week is determined by the Calendar’s first-day-of-week field. Its initial value is determined by the Calendar’s locale, and you can control it through getFirstDayOfWeek() and setFirstDayOfWeek(). This in turn means that the default behaviour for a Calendar in a European locale previously set to a Sunday will go back to the previous Friday, whereas a Calendar in the US locale would pick the next Friday instead.
If you have also set other fields after setting the day-of-week but before fields are calculated, it is a different story.
Default values?
Generally the default values of Calendar fields are current date and time in your JVM’s time zone (usually, but not always, the same as your device’s time zone).
You don’t need to care
The good news is that you don’t need to care. The Calendar class is long outmoded anyway, and it was also (seen in retrospect) poorly designed, so you should not use it. Instead use java.time, the modern Java date and time API. It is so much nicer to work with. Depending on your need, you may for example use LocalDate for a date or ZonedDateTime for a date and time of day with time zone.
The modern classes offer you a great deal of better clarity and more flexibility. For example:
LocalDate ld = LocalDate.now(ZoneId.of("Pacific/Saipan"));
// the following calls do what the method names say
ld = ld.with(TemporalAdjusters.next(DayOfWeek.FRIDAY));
ld = ld.with(TemporalAdjusters.nextOrSame(DayOfWeek.FRIDAY));
ld = ld.with(TemporalAdjusters.previous(DayOfWeek.FRIDAY));
ld = ld.with(TemporalAdjusters.previousOrSame(DayOfWeek.FRIDAY));
// set to Friday in the same ISO week
ld = ld.with(ChronoField.DAY_OF_WEEK, DayOfWeek.FRIDAY.getValue());
// set to Friday in the same US week
ld = ld.with(WeekFields.SUNDAY_START.dayOfWeek(),
DayOfWeek.FRIDAY.get(WeekFields.SUNDAY_START.dayOfWeek()));
Question: Can I use java.time on Android?
Yes, java.time works nicely on Android devices. It just requires at least Java 6.
In Java 8 and later and on new Android devices (from API level 26, I’m told) the new API comes built-in.
In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310, where the modern API was first described).
On (older) Android, use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. Make sure you import the date and time classes from package org.threeten.bp and subpackages.
Links
Oracle tutorial: Date Time, explaining how to use java.time.
ThreeTen Backport project
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
Java Specification Request (JSR) 310.
Its will be nex Friday
Friday, 23 February 2018 year., 20:44:17.353
Default values is this Year
what are the default values
Calendar rightNow = Calendar.getInstance(); //the default is the current time/date
next Friday or the past Friday or maybe the closest?
next time/date, therefore, the answer is next Friday.
see the documentation
it turns out that using myCalender.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY)
is a complete mess, it may set the day to next or the past Friday, I have been trying a lot but couldn't figure the logic!
Anyway, all I needed was to set the calendar to a particular day in the next week, and I managed to do this using the answer to that question ..
set the calendar to next Thursday
I trying to calculate a date window based on 3 days prior and after the current plus 30,60,90 days. I really don't no a correct way to do it with calendar this is besides this dirty way.
public static void main(String []args) throws ParseException {
Calendar cal = GregorianCalendar.getInstance();
System.out.println("Curent date is " + cal.getTime() + "\n");
int [] remainingPeriodArr = {30,60,90,180};
int [] expiredArr = {30,60,90};
for(int i = 0; i < remainingPeriodArr.length; i++) {
getSupportPeriod(remainingPeriodArr[i]);
}
for(int i = 0; i < expiredArr.length; i++) {
getSupportPeriod(expiredArr[i]);
}
}
public static void getSupportPeriod(int period) {
Calendar c1 = GregorianCalendar.getInstance();
c1.add(Calendar.DATE, -3);
c1.add(Calendar.DATE, period);
System.out.println( period + " days from prior window " + c1.getTime() + "\n");
Calendar c2 = GregorianCalendar.getInstance();
c2.add(Calendar.DATE, 3);
// Date d2 = c2.getTime();
c2.add(Calendar.DATE, period);
System.out.println( period+ " days in the future window " + c2.getTime() + "\n");
}
}
Barring the new JDK8 date library or Joda Time, the easiest is to work off the current time in milliseconds:
long now = System.currentTimeMilliseconds();
long threeDaysAgoMillis = now - (3 * 24 * 60 * 60 * 1000);
long nowPlus30Millis = now + (30 * 24 * 60 * 60 * 1000);
Date threeDaysAgo = new Date(threeDaysAgoMillis);
Date nowPlus30 = new Date(nowPlus30Millis);
If you're using JDK8, check out this tutorial. If you can use Joda time, look here.
If you go the old JDK way then be aware of following pitfalls:
A) Avoid inherited static methods in general, but use the concrete value object type.
Calendar c1 = GregorianCalendar.getInstance();
Better use:
GregorianCalendar c1 = new GregorianCalendar();
Why? If you are in Thailand you will not get the gregorian calendar with your approach by using a static Calendar-method on GregorianCalendar-class. Instead you get the buddhist calendar.
B) Use domain specific type dependent on your problem
Unfortunately GregorianCalendar is not a date-only type so it does not fit well your requirements for date arithmetic. And in old JDK there is no such type at all so you have to live with ugly work-arounds. In Java 8 you can use java.time.LocalDate, in JodaTime you can use org.joda.time.LocalDate. In my coming time library you can use net.time4j.PlainDate (first release still this month).
C) Otherwise try to mimic a plain date type
Using GregorianCalendar you need to zero out all time fields, that is:
gcal.set(year, month, dayOfMonth);
gcal.set(Calendar.HOUR_OF_DAY, 0);
gcal.set(Calendar.MINUTE, 0);
gcal.set(Calendar.SECOND, 0);
gcal.set(Calendar.MILLISECOND, 0);
Note that this approach is not perfect under some rare conditions related to time zone offset changes, but will probably be sufficient in US and Europe.
If you evaluate such calendar objects as result of addition operations like add(Calendar.DATE, period), you should only print its date part and ignore the time part - in most cases by selecting a date-only format according to your local or as ISO-8601-format (mostly limited to year, month, day-of-month).
If you compare such calendar objects then don't apply comparisons based on the method getTime(), but only by explicit extracting year, month and day-of-month (writing a specialized Comparator is a good idea).
D) Avoid self-made date/time-arithmetic, trust the library
Code like long nowPlus30Millis = now + (30 * 24 * 60 * 60 * 1000); will probably fail if you have a daylight-saving switch in the meantime. The add()-method of java.util.GregorianCalendar can take this in account, but in general not self-made arithmetic.
tl;dr
LocalDate.now().plusDays( 3 )
java.time
The modern approach uses the java.time classes.
LocalDate
The LocalDate class represents a date-only value without time-of-day and without time zone.
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment, so your results may vary. Better to specify your desired/expected time zone explicitly as an argument.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the JVM’s current default is applied implicitly. Better to be explicit, as the default may be changed at any moment during runtime by any code in any thread of any app within the JVM.
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.
LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;
Math
One way to add days is with the LocalDate::plusDays method. Similar for subtraction.
LocalDate later = ld.plusDays( 3 ) ;
LocalDate earlier = ld.minusDays( 3 ) ;
Or, use objects to represent the span-of-time to be added or subtracted. This has the advantage of being able to label your span-of-time with variable name. For years-months-days, use Period. For hours-minutes-seconds, use Duration.
Period periodBookIsLate = Period.ofDays( 3 ) ;
LocalDate dueDate = ld.plus( periodBookIsLate ) ;
LocalDateRange
You may find the LocalDateRange class useful, available from the ThreeTen-Extra project.
LocalDateRange thirtyDayRange = LocalDateRange.of( ld.minusDays( 30 ) , ld.plusDays( 30 ) ) ;
Learn about the handy methods in that class such as abuts, contains, intersection, and more.
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
Later versions of Android bundle implementations of the java.time classes.
For earlier Android, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
I'm working on a reporting system using Java 6 and SQL Server 2008. For some queries I want to look at the data by week number. I'm using Java to fill in gaps in the the data to make a continuous time line and I have found that
java.util.Calendar cal = new java.util.GregorianCalendar();
cal.set(2012, 0, 1);
cal.get(Calendar.WEEK_OF_YEAR);
and
org.joda.time.DateTime date = new org.joda.time.DateTime(2012, 01, 01, 0, 0);
date.getWeekOfWeekyear();
return a different week number to
DATEPART(WEEK, '2012-01-01')
Is there an approach to resolving this difference or will I have to choose to use SQL Server or Java week numbers?
TIA
Java is more sophisticated when it comes to calculating week numbers, whereas SQL-Server DATEPART(WEEK... is more simplistic. I found the following documented here
"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() "
I think this defaults to the ISO standards which is the first week of the year with a thursday in (Monday-Sunday weeks where at least 4 days are the year). Consider using:
In SQL Server the DATEPART(WEEK, ..) function is much more simplistic, it simply calculates the number of week boundaries (as defined by DATEFIRST) between the first of january, and the input date, so the 1st January will always be week 1. You may wish to consider using:
SELECT DATEPART(ISO_WEEK, '01/01/2012')
This gets the week number as defined by the ISO standards, which is the first week of the year with a thursday in (Monday-Sunday weeks where at least 4 days are the year).
Since, as stated SQL Server is more simplistic in it's calculations, this can't be configured, which means that you will need to configure your week numbers within Java. Simply ensure you set up your calendar in Java with the correct values for getFirstDayOfWeek() and getMinimalDaysInFirstWeek():
public static Calendar getISOCalendar() {
Calendar calendar = Calendar.getInstance();
calendar.setMinimalDaysInFirstWeek(4);
calendar.setFirstDayOfWeek(Calendar.MONDAY);
return calendar;
}
Then you can esnsure consistent week numbers.
public static void main(String args[]) {
Calendar calendar = getISOCalendar();
calendar.set(2012,0,1);
System.out.println(calendar.get(Calendar.WEEK_OF_YEAR));
}
------
52
According to their respective docs, java.util.calendar, joda, and DATEPART all return an integer between 1 and 53 indicating the week. This value is based on what is defined as the first day of the week and the default calendar (e.g. Gregorian, Chinese). I would check your defaults or see what each thinks the first day of the week is.
I think it might have something to do with 2011 and the idea that it has 53 weeks according to SQLServer. Looking at Jan / New Year SQL problems!, this solution might help to handle the SQLServer stuff better:
DATEPART(WEEK, DATEADD(WEEK, -1, '2012-01-01'))
tl;dr
int iso8601WeekNumber =
ZonedDateTime.now( ZoneId.of ( "America/Montreal" ) )
.get( IsoFields.WEEK_OF_WEEK_BASED_YEAR )
Many definitions of a week
There are many definitions of a week.
For some people the first day of a week is a Sunday, others Mondays, and still others some other day.
For some people the first week of the year contains January 1st, while some other folks count the first week as the one containing that start-of-week day mentioned above, while others count week one as containing a specific day-of-week.
So you should never assume the meaning of a "week" or "week number" without studying the documentation.
Avoid legacy date-time classes
In general, you should avoid the old legacy date-time classes bundled with the earliest versions of Java as they are poorly-designed, confusing, and troublesome.
Here specifically, the java.util.Calendar class has a definition of week that varies by locale. So do not use this if you want reliable constant results.
ISO 8601
The ISO 8601 standard defines formats and related issues for date-time values. It specifically defines the meaning of a week and week-of-year:
Week runs from Monday-Sunday, numbered 1-7 where Monday = 1.
Week # 1 contains the first Thursday of the year, yielding 52 or 53 weeks per year.
Joda-Time
The Joda-Time library uses the ISO 8601 standard definition of week and week-of-year.
However, be aware that the Joda-Time project is now in maintenance mode, with the team advising migration to java.time.
java.time
The java.time classes use the ISO 8601 definition of a week: Week # 1 has first Thursday, with week running Monday-Sunday.
The IsoFields class defines a week-based year. We can ask for the:
Week-of-year number (WEEK_OF_WEEK_BASED_YEAR)
Year number of the week-based year (WEEK_BASED_YEAR).
First we get the current date-time.
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now ( zoneId );
Interrogate that date-time object, asking about the standard week-based year.
int week = now.get ( IsoFields.WEEK_OF_WEEK_BASED_YEAR );
int weekYear = now.get ( IsoFields.WEEK_BASED_YEAR );
Dump to console.
System.out.println ( "now: " + now + " is week: " + week + " of weekYear: " + weekYear );
now: 2016-01-17T20:55:27.263-05:00[America/Montreal] is week: 2 of weekYear: 2016
For more info, see this similar Question: How to calculate Date from ISO8601 week number in Java.
WeekFields
In java.time you can also call upon the WeekFields class, such as WeekFields.ISO.weekBasedYear(). Should have the same effect as IsoFields in later versions of Java 8 or later (some bugs were fixed in earlier versions of Java 8).
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, & java.text.SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to java.time.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8 and SE 9 and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
System.out.println("get date range from week number and year in java");
System.out.println(); // print a blank line
// get the input from the user
Scanner sc = new Scanner(System.in);
System.out.print("Enter the week : ");
int weekNumber = sc.nextInt();
System.out.print("Enter the Year: ");
int year = sc.nextInt() ;
Calendar cal = Calendar.getInstance();
//cal.setTime(new Date());
cal.set(Calendar.YEAR, year);
cal.set(Calendar.WEEK_OF_YEAR, weekNumber);
SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
System.out.println(formatter.format(cal.getTime())); // start date
cal.add(Calendar.DAY_OF_WEEK, 6);
System.out.println(formatter.format(cal.getTime())); // end date
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 ...
Anyone know a simple way using Java calendar to subtract X days from a date?
I have not been able to find any function which allows me to directly subtract X days from a date in Java. Can someone point me to the right direction?
Taken from the docs here:
Adds or subtracts the specified amount of time to the given calendar field, based on the calendar's rules. For example, to subtract 5 days from the current time of the calendar, you can achieve it by calling:
Calendar calendar = Calendar.getInstance(); // this would default to now
calendar.add(Calendar.DAY_OF_MONTH, -5).
You could use the add method and pass it a negative number. However, you could also write a simpler method that doesn't use the Calendar class such as the following
public static void addDays(Date d, int days)
{
d.setTime( d.getTime() + (long)days*1000*60*60*24 );
}
This gets the timestamp value of the date (milliseconds since the epoch) and adds the proper number of milliseconds. You could pass a negative integer for the days parameter to do subtraction. This would be simpler than the "proper" calendar solution:
public static void addDays(Date d, int days)
{
Calendar c = Calendar.getInstance();
c.setTime(d);
c.add(Calendar.DATE, days);
d.setTime( c.getTime().getTime() );
}
Note that both of these solutions change the Date object passed as a parameter rather than returning a completely new Date. Either function could be easily changed to do it the other way if desired.
Anson's answer will work fine for the simple case, but if you're going to do any more complex date calculations I'd recommend checking out Joda Time. It will make your life much easier.
FYI in Joda Time you could do
DateTime dt = new DateTime();
DateTime fiveDaysEarlier = dt.minusDays(5);
tl;dr
LocalDate.now().minusDays( 10 )
Better to specify time zone.
LocalDate.now( ZoneId.of( "America/Montreal" ) ).minusDays( 10 )
Details
The old date-time classes bundled with early versions of Java, such as java.util.Date/.Calendar, have proven to be troublesome, confusing, and flawed. Avoid them.
java.time
Java 8 and later supplants those old classes with the new java.time framework. See Tutorial. Defined by JSR 310, inspired by Joda-Time, and extended by theThreeTen-Extra project. The ThreeTen-Backport project back-ports the classes to Java 6 & 7; the ThreeTenABP project to Android.
The Question is vague, not clear if it asks for a date-only or a date-time.
LocalDate
For a date-only, without time-of-day, use the LocalDate class. Note that a time zone in crucial in determining a date such as "today".
LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) );
LocalDate tenDaysAgo = today.minusDays( 10 );
ZonedDateTime
If you meant a date-time, then use the Instant class to get a moment on the timeline in UTC. From there, adjust to a time zone to get a ZonedDateTime object.
Instant now = Instant.now(); // UTC.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
ZonedDateTime tenDaysAgo = zdt.minusDays( 10 );
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.
int x = -1;
Calendar cal = ...;
cal.add(Calendar.DATE, x);
See java.util.Calendar#add(int,int)
Instead of writing my own addDays as suggested by Eli, I would prefer to use DateUtils from Apache. It is handy especially when you have to use it multiple places in your project.
The API says:
addDays(Date date, int amount)
Adds a number of days to a date returning a new object.
Note that it returns a new Date object and does not make changes to the previous one itself.
I faced the same challenge where I needed to go back by 1 day (should be able to roll back by one even if previous day falls into previous year or months).
I did following, basically subtracted by 24 hours for 1 day.
someDateInGregorianCalendar.add(Calendar.HOUR, -24);
Alternatively, I could also do
GregorianCalendar cal = new GregorianCalendar();
cal.set(Calendar.YEAR, 2021);
cal.set(Calendar.MONTH, 0);
cal.set(Calendar.DATE, 1);
System.out.println("Original: " + cal.getTime());
cal.add(Calendar.DATE, -1);
System.out.println("After adding DATE: " + cal.getTime());
OUTPUT:
Original: Fri Jan 01 15:08:33 CET 2021
After adding DATE: Thu Dec 31 15:08:33 CET 2020
It can be done easily by the following
Calendar calendar = Calendar.getInstance();
// from current time
long curTimeInMills = new Date().getTime();
long timeInMills = curTimeInMills - 5 * (24*60*60*1000); // `enter code here`subtract like 5 days
calendar.setTimeInMillis(timeInMills);
System.out.println(calendar.getTime());
// from specific time like (08 05 2015)
calendar.set(Calendar.DAY_OF_MONTH, 8);
calendar.set(Calendar.MONTH, (5-1));
calendar.set(Calendar.YEAR, 2015);
timeInMills = calendar.getTimeInMillis() - 5 * (24*60*60*1000);
calendar.setTimeInMillis(timeInMills);
System.out.println(calendar.getTime());
I believe a clean and nice way to perform subtraction or addition of any time unit (months, days, hours, minutes, seconds, ...) can be achieved using the java.time.Instant class.
Example for subtracting 5 days from the current time and getting the result as Date:
new Date(Instant.now().minus(5, ChronoUnit.DAYS).toEpochMilli());
Another example for subtracting 1 hour and adding 15 minutes:
Date.from(Instant.now().minus(Duration.ofHours(1)).plus(Duration.ofMinutes(15)));
If you need more accuracy, Instance measures up to nanoseconds. Methods manipulating nanosecond part:
minusNano()
plusNano()
getNano()
Also, keep in mind, that Date is not as accurate as Instant. My advice is to stay within the Instant class, when possible.
Someone recommended Joda Time so - I have been using this CalendarDate class http://calendardate.sourceforge.net
It's a somewhat competing project to Joda Time, but much more basic at only 2 classes. It's very handy and worked great for what I needed since I didn't want to use a package bigger than my project. Unlike the Java counterparts, its smallest unit is the day so it is really a date (not having it down to milliseconds or something). Once you create the date, all you do to subtract is something like myDay.addDays(-5) to go back 5 days. You can use it to find the day of the week and things like that.
Another example:
CalendarDate someDay = new CalendarDate(2011, 10, 27);
CalendarDate someLaterDay = today.addDays(77);
And:
//print 4 previous days of the week and today
String dayLabel = "";
CalendarDate today = new CalendarDate(TimeZone.getDefault());
CalendarDateFormat cdf = new CalendarDateFormat("EEE");//day of the week like "Mon"
CalendarDate currDay = today.addDays(-4);
while(!currDay.isAfter(today)) {
dayLabel = cdf.format(currDay);
if (currDay.equals(today))
dayLabel = "Today";//print "Today" instead of the weekday name
System.out.println(dayLabel);
currDay = currDay.addDays(1);//go to next day
}
Eli Courtwright second solution is wrong, it should be:
Calendar c = Calendar.getInstance();
c.setTime(date);
c.add(Calendar.DATE, -days);
date.setTime(c.getTime().getTime());