I have a little question about internal java working and Calendar, i dont understand why when i use for example:
Calendar c = Calendar.getInstance();
mesInt = c.get(Calendar.MONTH);
System.out.println(mesInt);
If then i print mesInt, if the actually month is february i obtain mesInt = 1;
is there any special reason for that? I would like to know because i had problems before with my database, and i would like if it is possible to know the solution of start by 0 the month.
Thanks for all, and sorry if the questions is duplicated i haven not found it.
PD: i know that is zero-based, but i would like to know the real reason for that.
PD2: sry for my bad english. I know the solution i would like to know the reason of that.
The documentation states the first month is 0.
i would like to know the real reason for that.
I suspect starting at 0 is easier to calculate. I am not sure any one person will admit to designing Calendar. Perhaps it made sense at the time as many of the numberings for years, AM/PM etc start at 0. BTW days of the week start at 1.
know i would like if it is possible to know the solution.
Use
int mesInt = c.get(Calendar.MONTH) + 1;
BTW For me the strange one is UNIDECIMBER when uni-deci mean 11 not 13.
Months are 0 based. I'm not sure of the reason why...
So when using either get or set with month you need to remember to either +1 or -1 as required.
Calendar c = Calendar.getInstance();
int mesInt = c.get(Calendar.MONTH) + 1;
c.set(Calendar.MONTH, mesInt - 1);
Months in Calendar starts from zero it means that January -> 0 February -> 1 etc.
The Specification of Calendar.MONTH is as follows:
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.
Essentially for all practical purposes : January is 0 and December is 11.
I bet it's for the same reason array indices start from 0. It's just how it is. February is often displayed as "2", but displaying or printing values is different from using them in code.
Related
I know there's a lot of questions about this but I couldn't find one that match with my case.
I have to know if a date is exactly x months after another.
With ChonoUnit it's just not possible because 2020/05/25 and 2020/07/27or 2020/07/25 will return the same number of month and I can't handle the difference with the days. I have the same type of response with JodaTime
I tried with Perdiod and it's not relevant either.
LocalDate localDate = LocalDate.of(2020,1,30);
LocalDate toTest = localDate.plusMonths(1L); // returns 2020/02/29
Period.between(localDate, toTest);
returns months 0, days 30
I read that the endDate is exclusive, so I tried adding a day
LocalDate localDate = LocalDate.of(2020,1,30);
LocalDate toTest = localDate.plusMonths(1L); // returns 2020/02/29
Period.between(localDate, toTest.plusDays(1L));
returns months 1, days 1
So my question is : Is there a method to get this information that is compatible with the way LocalDate handles the months ?
Edit
Ok, I was not precise enough in my request. I know a month is not an absolute value, and my conception of a month doesn't matter.
In my case I have a LocalDate input that I can't contraint. I have to generate outputs every X months minus Y number of days.
Knowing that I test in a schedule if today is exactly X months after my input minus Y days (to be precise, I test if the number of month between the two dates modulo X equals 0). But if my input is the 31st of the month, Period will never return me 1 months, 0 days. If it's the 30st and my output should trigger in february it will never be neither.
Given that if on the short months the output occurs one day before the inexistant logic date it's not a problem.
The exemple I gave with LocalDate is just extracted from my tests but it's the way I thank I could do the thing, thus without doing myself a complicated algorithm with many conditions.
I think you in your description you tried with January and February. That might be causing problem. So you have to manually handle this case. Otherwise your code is working.
A month is not exact time unit. Think about it: we can tell exactly how many seconds are in 1 minute, in 1 hour, 1 day and 1 week. But the number of seconds for different months would be different. So you need to define the logic what do you see as two dates that differ exactly one month? Once you define all the expected behaviors (including such cases as what is exactly one month from January 30th? Feb 28/29? or march 1st?) then you can see if there is anything out of the box that works for you or you need to implement your own logic
I have to know if a date is exactly x months after another.
That is an unclear request. One obvious interpretation would appear to be:
int monthA = a.getYear() * 12 + a.getMonthValue();
int monthB = b.getYear() * 12 + b.getMonthValue();
// Months.between can probably also be used instead of this math.
return a.getDayOfMonth() == b.getDayOfMonth() && (monthA - monthB) == x;
But that does mean it is -impossible- for a date to exist that is 'exactly 1 month after' March 30th: There is no feb 30th and there never will be.
Is that what you really wanted? Given that the length of a month depends on which month you ask, 'exactly 1 month later' is not a sensible question to ask. Hence: What do you actually mean?
Same day-of-month, X months later? (And realizing that there are many dates for which there cannot be such a date).
X days afterwards, where X is some formulaic approach based on which month we are in.
I probably still haven’t got it. Allow me a shot in spite, elaborating on my idea from the comment: If you like the way LocalDate.plusMonths() does, then use that method.
int monthsBetween = 3; // X
int daysBefore = 11; // Y
LocalDate originalDate = LocalDate.of(2020, Month.JANUARY, 30);
int nextTimeCount = 1; // next time to generate output will be the 1st time
LocalDate nextDate = originalDate.plusMonths(nextTimeCount * monthsBetween).minusDays(daysBefore);
LocalDate today = LocalDate.now(ZoneId.systemDefault());
while (! nextDate.isAfter(today)) {
System.out.format("Generating output no. %d for %s%n", nextTimeCount, nextDate);
nextTimeCount++;
nextDate = originalDate.plusMonths(nextTimeCount * monthsBetween).minusDays(daysBefore);
}
Output when I ran just now (December 30):
Generating output no. 1 for 2020-04-19
Generating output no. 2 for 2020-07-19
Generating output no. 3 for 2020-10-19
Assuming that your program will not be running uninterrupted for months you will need some way to persist the data, of course. So my code will not work as it stands, but if the behaviour is otherwise as expected, you can probably use the same mthod calls that I am using.
So Im working on an Calendar programm and to change the Months im asking for the int of the month.
If I type calendar.get(Calendar.JANUARY) i get 1 as return, which is correct because first month. But if I type calendar.get(Calendar.FEBUARY) i get 2018 in respond which of course is wrong. Does anyone know what the problem could be?
Calendar cal1 = new GregorianCalendar();
int month = cal1.get(Calendar.JANUARY);
int month2 = cal1.get(Calendar.FEBRUARY);
int year = cal1.get(Calendar.YEAR);
java.time
T.J. Crowder’s answer is correct. Allow me to supply the real, good and modern solution to your problem.
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("Atlantic/Stanley"));
// 2018-05-21T05:02:23.942763-03:00[Atlantic/Stanley]
Month monthEnum = zdt.getMonth(); // MAY
int monthNumber = zdt.getMonthValue(); // 5
int year = zdt.getYear(); // 2018
I ran the code just now and have given results in comments after each code line. Please put your desired time zone where I have put Atlantic/Stanley since the month does not change at the same point in time in different time zones. Do you agree with me that this code is clearer and more natural and leaves less room for confusion? BTW, if you’re only interested in the date, not the time of day, use LocalDate instead of ZonedDateTime, the rest of the code will be the same.
To get the numbers of specific months:
int januaryNumber = Month.JANUARY.getValue(); // 1
int februaryNumber = Month.FEBRUARY.getValue(); // 2
What happened in your code?
As T.J. Crowder has already said, Calendar.get expects a field number, for example Calendar.MONTH or Calendar.YEAR. Calendar.JANUARY is 0. Zero?! It’s another confusing thing about Calendar, month numbers are 0-based, that is, they go from 0 for January through 11 for December. Anyway, 0 is also the field number of Calendar.ERA. GregorianCalendar uses 0 for BC (or more religion neutral: BCE for before common era) and 1 for AD (CE, common era). Since your date is in the common era, you get 1. Which, by the way, would have been incorrect for month of January since months are 0-based.
Similarly, Calendar.FEBRUARY equals 1 and coincides with field number Calendar.YEAR, which I why you got the year.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Question: Why is January month 0 in Java Calendar?
Calendar#get gets a field value. Calendar.JANUARY is not a field number, it's a potential field value. The only static fields in Calendar that you use with get (and set) are the ones whose descriptions start with "Field number for get and set...".
To get the month, use cal1.get(Calendar.MONTH).
The Calendar API is...unfortunate, not least because it predates enums and so int was used for get/set's field identifier parameter where an enum was really needed. While get takes an int, and Calendar.JANUARY is an int, they're ints in different domains. See Ole V.V.'s answer for the modern, dramatically-improved alternative: java.time.
So I'm using JodaTime in an app I've got and I need a way to tell if the current time is within 6 hours of midnight. Well actually I need to know if the time is within 8 hours of 2am, but JodaTime seems to provide a constant for midnight so I was looking at that. Anyway, I've tried a number of different things but nothing quite works. Any help or pointers would be appreciated.
This can be accomplished simply by using JodaTime without any math involved.
DateTime time = new DateTime(DateTimeZone.UTC);
Period period = new Period(time, time.plusDays(1).toDateMidnight());
System.out.println(period.getHours());
The time.plusDays(1).toDateMidnight() (yes, I was lazy), is so that I'm comparing with the next midnight, and not with today's midnight (which already passed).
If you want to check both before and after, just check both periods.
I would suggest using a DateTime object.
DateTime date = new DateTime();
int i = getSecondOfDay();
Then using a little math we can find the number of seconds 6pm would be.
18hours*60min*60seconds= 64800 seconds.
if ( i > 64800 ){
// Do what you need here
}
I assumed you needed to tell if it was 8 hours of am of this current day and not a specific day.
This is a bit hardcoded and pcalcao's answer is probably more flexible:
private static boolean isLessThan8HoursFrom2AM(DateTime date) {
return (date.getHourOfDay() >= 18 || date.getHourOfDay() < 10);
}
You can also check if the time of day is 6 hours from midday.
if(Math.abs(timeOfDay - 43200) >= 21600) // first or last 6 hours of day.
I retrieve a Date from the database using the ResultSet rsExpid.
Date joindate = rsExpid.getDate("join_date_ad");
System.out.println(joindate);
int year = joindate.getYear();
System.out.println(year);
int month =joindate.getMonth();
System.out.println(month);
int day = joindate.getDay();
System.out.println(day);
dateTimeJoin4.setDate(year, month, day);
When I print joindate to the console it shows correctly as 2011-08-03, but when I print the year to the console I was amazed to see 111. Similarly printing the month produced 7 and the day resulted in 3.
The variable dateTimeJoin4 is my SWT DateTime. It is not setting any value and it is also not giving any error message. Could please anybody help me on this?
Chances are you haven't read the documentation for Date.getYear and Date.getMonth:
Returns a value that is the result of subtracting 1900 from the year that contains or begins with the instant in time represented by this Date object, as interpreted in the local time zone.
and
Returns a number representing the month that contains or begins with the instant in time represented by this Date object. The value returned is between 0 and 11, with the value 0 representing January.
respectively. Likewise Date.getDay returns the day of the week, not the day of the month - you want Date.getDate() for that (or preferrably a different API entirely, either Calendar or Joda Time).
This has nothing to do with SWT's DateTime type - after all, you only use that in the last line. When something behaves unusually, your first port of call should be the documentation. SWT's DateTime.setDate method is documented to require a year between 1752 and 9999, so 111 will be confusing it. Admittedly it would have been nice if it had thrown an exception, but even so...
The fact that you're calling deprecated methods should have been a hint to you, although Calendar also uses 0-11 for its months.
Personally I would strongly encourage you to use Joda Time for as much of your date and time work as you can. It's a far superior date and time API to the one built into Java. It's not immediately clear whether it's worth you using it here (if this is all you have to do) but if you're doing anything at all significant (including parsing, formatting or any kind of arithmetic) you should be using it.
I tried using this method and it worked correctly so this method can be useful to other.
Calendar startCal = Calendar.getInstance();
startCal.setTime(joindate);
int months= startCal.get(Calendar.MONTH);
int years= startCal.get(Calendar.YEAR);
int days= startCal.get(Calendar.DAY_OF_MONTH);
System.out.println(months+1);
System.out.println(years);
System.out.println(days);
dateTimeJoin4.setDate(years, months+1, days);
getDay() return the position of the day not the date like suppose today is Monday it will return 1, it start from the sunday with 0 value.
as well as the getMonth() return the position as starting value is 0 for january at now you getting the 7 instead of 8.
for getting date you can use the SimpleDateFormat or DateFormat by passing the format string in that you can get it
example links
http://www.roseindia.net/java/javadate/date-format.shtml
http://www.java-examples.com/java-simpledateformat-class-example
I'm newish to Java and am trying to do somethings with dates. First I started using the Date class, which I found out was mostly deprecated so I switched over to Calendar.
Now I am getting weird values. for example the Month value for December is 0, not 12. And on those Calendars where it is giving me 0 for December it is also moving the year ahead one year.
It's weird!
What am I missing?
Thanks for your help.
-GG
EDIT FOR AN EXAMPLE:
So I am reading some line sin from a file such as this:
Johnny Graham H F 12-2-1973 Black
I parse it, and then for the Calendar I set:
int year = Integer.parseInt(stringVersionOfYear); // this value is 1973
Then later when I go to get the year back with a line like this:
calendar.get(Calendar.YEAR)
the value is 1974... And the month is 0 for
cal.get(Calendar.MONTH)
EDIT 2:
I am creating the Calendar like this:
Calendar outputCalendar = Calendar.getInstance();
outputCalendar.set(year, month, day);
The java.util.Date and Calendar classes are poorly designed (eg, the first day in a month is day 1 but the first month in a year is month 0). Many projects use the Joda Time package instead.
Months values are 0 thru 11; set a month to 12 and the date gets "normalized", incrementing the year by one and setting the month to 0. This makes it easy to "add a month" without having to worry about handling the overflow at year end.
EDIT: January=0, February=1,... December=11. When you set the month value to 12 you were asking for the 13th month, which got normalized to the first month of the following year.
Note that this normalization process happens in general -- Try to set the date to December 32nd and you'll get back January 1 of the following year. This means it's important to be careful when modifying individual fields of a Calendar object. If you create a default Calendar on, say, January 31st and then want to modify it to contain, say February 5th, the order in which you set the fields is important. If you change the month first you'll be creating February 31st, which will get normalized to March 2nd or 3rd (depending on the leap year) and then when you set the day to 5 the result is March 5th, not February 5th. You have the opposite problem in other cases, such as starting from any date in February and modifying to the 30th or 31st of any other month. In that case doing the month first results in the same type of problem.
The only safe way to modify a date is to use a method that sets all three values simultaneously, such as the set(int,int,int) method.
See this line?
outputCalendar.set(year, month, day);
Just change it like this:
outputCalendar.set(year, month - 1, day);
and then when you want to get the month, don't use this:
cal.get(Calendar.MONTH)
instead, use this:
(1+(cal.get(Calendar.MONTH)))
It's a pain, but it will fix the problem (I think).
The main piece of advice I have for you is: read the API! Calendar is indeed not the pinnacle of intuitive API design, but it is definitely usable if you take the time to read the javadoc. Learn the difference between .add and .roll. Check out what happens when you set a year (1973) into a Calendar initialized with the current date (default Calendar.getInstance).
Whining about API is all fine (we all do it), but in the end to find solutions start off by reading what the authors provided to you before asking relatively obtuse questions on the Internet.