Calendar.Month gives wrong output - java

I have been using java.util for all date and calendar representations. But I am facing a strange problem here. Calendar.MONTH, Calendar.DAY_OF_MONTH, etc all give wrong outputs. But when I use Calendar.getTime(), I get the right output. What might be the problem?
public class TestClass {
public static void main(String[] args) {
Calendar rightNow = Calendar.getInstance();
System.out.println(rightNow.MONTH);
System.out.println(rightNow.DAY_OF_MONTH);
System.out.println(rightNow.YEAR);
System.out.println(rightNow.getTime());
}
}
And the output for the same is:
2
5
1
Tue Jan 22 10:31:44 GMT+05:30 2013

System.out.println(rightNow.MONTH);
System.out.println(rightNow.DAY_OF_MONTH);
System.out.println(rightNow.YEAR);
System.out.println(rightNow.getTime());
You are printing Calendar constant values.
If you want values, you need to do get....
Example:
System.out.println(rightNow.get(Calendar.MONTH));
Read Calendar javadoc for more information.

Calendar.MONTH doesn't return the current month. It is a constant whose value is 2.
From the source:
public final static int MONTH = 2;
It is for use as a parameter in Calendar's get method
public int get(int field) {...}
The design of Calendar is from the early days of Java, when many of today's conventions were different, non-existant, or developing. Oracle (and earlier, Sun), would never let an API like the java.util.Calendar API become part of the standard API today.
And, for completeness, use Joda Time instead of Java's Date and Calendar API's.

java.time
ZonedDateTime rightNow = ZonedDateTime.now(ZoneId.of("Africa/Cairo"));
System.out.println(rightNow.getMonth());
System.out.println(rightNow.getMonthValue());
System.out.println(rightNow.getDayOfMonth());
System.out.println(rightNow.getYear());
System.out.println(rightNow);
Output when running just now was:
FEBRUARY
2
15
2019
2019-02-15T21:15:06.313809+02:00[Africa/Cairo]
Don’t use Calendar
The Calendar class is confusing and suffers from poor design, so no wonder that you’re wondering. Fortunately it was replaced the year after you asked this quesion by ZonedDateTime and other classes in java.time, the modern Java date and time API. So never use Calendar again now.
The Calendar class was trying to be very general, so instead of a getMonth method, etc., it had the notion of fields that could be read and set. Since it was designed long before Java had enums, each field had a number and a named constant for that number. So YEAR (of era) was 1, MONTH was 2, etc. To get the value of the field of a Calendar object you were supposed to call the get method passing the appropriate named constant, for example rightNow.get(Calendar.MONTH). Using just rightNow.MONTH is a regularly repeated mistake. It just gives you the value of the constant, 2.
Link
Oracle tutorial: Date Time explaining how to use java.time.

Calendar now = Calendar.getInstance();
out.println("month now= " + (now.get(Calendar.MONTH)+1));
OR with GregorianCalender:
GregorianCalendar nu = new GregorianCalendar();
int day = nu.get(Calendar.DAY_OF_MONTH);
int month = (nu.get(Calendar.MONTH)+1); //month +1 because january`==0
int year= nu.get(Calendar.YEAR);
int hour= nu.get(Calendar.HOUR_OF_DAY);
int minutes= nu.get(Calendar.MINUTE);
here

Related

Incorrect data returned by Calendar API

In our business requirement we are supposed to find out the first day of the week.
Since the client is European so I used following code to get it.
But, issue is when I run this code I am getting 2 as the answer where as I am expecting 1.
public class Test{
public static void main(String[] args) {
TimeZone eu = TimeZone.getTimeZone("Europe/Berlin");
Locale de = Locale.forLanguageTag("de");
int firstDayOfWeek = Calendar.getInstance(eu, de).getFirstDayOfWeek();
System.out.println(firstDayOfWeek);
}
}
Can some one help me understand this behavior.
Look at the docs:
Gets what the first day of the week is; e.g., SUNDAY in the U.S., MONDAY in France.
and here:
public static final int MONDAY 2
This shows that the return value depends on the locale.
If we print this:
System.out.println(firstDayOfWeek == Calendar.MONDAY);
We'll see true. This means that the first day of week is indeed Monday. It's just that you thought Monday is encoded by 1. In fact, Sunday is encoded as 1.
Locale de = Locale.forLanguageTag("de");
WeekFields wf = WeekFields.of(de);
DayOfWeek firstDayOfWeek = wf.getFirstDayOfWeek();
System.out.println(firstDayOfWeek);
This prints:
MONDAY
Don’t use the confusing old Calendar class. You got 2 as the first day of the week. But weren’t you supposed to get 1? Or 0? How are days of the week numbered? Forget about numbers, use the DayOfWeek enum from java.time, the modern Java date and time API.
For prettier output use DayOfWeek.getDisplayName or a DateTimeFormatter. If you do need a number, use DayOfWeek.getValue:
System.out.println(firstDayOfWeek.getDisplayName(TextStyle.FULL, de));
System.out.println(firstDayOfWeek.getValue());
Output is:
Montag
1
PS Also don’t use TimeZone and the other long outdated date and time classes. java.time is so much nicer to work with. This fact shows nicely in this example, but its typical, certainly no coincidence.
Link: Oracle tutorial: Date Time explaining how to use java.time.
According to the javadoc, MONDAY's valus is 2.

Calendar.getTime().getYear() gives back 0113 instead of 2013

I'm making a little game. When the game is starting for the first time i saves the time since 01.01.1970 in seconds in the SharedPreferences.
Now i want to give this date out on my screen in this form: DD.MM.YYYYY
I used the Calendar function but it give back 02.04.0113 so, there are missing 1900 Years.
Here is my Code:
private void initBornTXT() {
SharedPreferences pref = getSharedPreferences("LIFE", 0);
long born = pref.getLong("BIRTHDAY", 0);
Calendar c = Calendar.getInstance();
c.setTimeInMillis(0);
c.add(Calendar.SECOND, (int)born);
int year = c.getTime().getYear();
int month = c.getTime().getMonth();
int day = c.getTime().getDay();
String string_born = String.format("%02d.%02d.%04d", day, month, year);
TextView born_txt = (TextView)findViewById(R.id.textViewBorn);
born_txt.setText(string_born);
}
What coud be wrong?
Nothing's wrong. You've just not looked at the documentation for the method you're calling, Date.getYear():
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.
Note that you should have received a warning that you're using a deprecated API: don't just ignore those warnings.
Also, do yourself a favour and don't do the formatting yourself: use SimpleDateFormat instead. (Or ideally, use Joda Time instead...) That way you can avoid the month being wrong, too... you may not have noticed that you're a month off due to months being 0-based, which is common to both Calendar and Date.
That's normal, documented behavior. See JavaDoc for Date#getYear().
A better way to get the year would be:
c.get(Calendar.YEAR)
You're using getTime, which returns a date object. Dates are based on 0=1900. So this is the expected output. Use a SimpleDateFormat instead.
Kudos for creating a Y2K bug though :)

How to generate a Date from just Month and Year in Java?

I need to generate a new Date object for credit card expiration date, I only have a month and a year, how can I generate a Date based on those two? I need the easiest way possible. I was reading some other answers on here, but they all seem too sophisticated.
You could use java.util.Calendar:
Calendar calendar = Calendar.getInstance();
calendar.clear();
calendar.set(Calendar.MONTH, month);
calendar.set(Calendar.YEAR, year);
Date date = calendar.getTime();
java.time
Using java.time framework built into Java 8
import java.time.YearMonth;
int year = 2015;
int month = 12;
YearMonth.of(year,month); // 2015-12
from String
YearMonth.parse("2015-12"); // 2015-12
with custom DateTimeFormatter
import java.time.format.DateTimeFormatter;
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM yyyy");
YearMonth.parse("12 2015", formatter); // 2015-12
Conversions
To convert YearMonth to more standard date representation which is LocalDate.
LocalDate startMonth = date.atDay(1); //2015-12-01
LocalDate endMonth = date.atEndOfMonth(); //2015-12-31
Possibly a non-answer since you asked for a java.util.Date, but it seems like a good opportunity to point out that most work with dates and times and calendars in Java should probably be done with the Joda-Time library, in which case
new LocalDate(year, month, 1)
comes to mind.
Joda-Time has a number of other nice things regarding days of the month. For example if you wanted to know the first day of the current month, you can write
LocalDate firstOfThisMonth = new LocalDate().withDayOfMonth(1);
In your comment you ask about passing a string to the java.util.Date constructor, for example:
new Date("2012-09-19")
This version of the constructor is deprecated, so don't use it. You should create a date formatter and call parse. This is good advice because you will probably have year and month as integer values, and will need to make a good string, properly padded and delimited and all that, which is incredibly hard to get right in all cases. For that reason use the date formatter which knows how to take care of all that stuff perfectly.
Other earlier answers showed how to do this.
Like
SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM");
Date utilDate = formatter.parse(year + "/" + month);
Copied from Create a java.util.Date Object from a Year, Month, Day Forma
or maybe like
DateTime aDate = new DateTime(year, month, 1, 0, 0, 0);
Copied from What's the Right Way to Create a Date in Java?
The most common sense approach would be to use the Date("YYYY-MM-DD") constructor even though it is deprecated. This is the easiest way to create a date on the fly. Screw whoever decided to deprecate it. Long live Date("YYYY-MM-DD")!!!
Don’t use this answer. Use the answers by Przemek and Ray Toel. As Przemek says, prefer to use a YearMonth for representing year and month. As both say, if you must use a date, use LocalDate, it’s a date without time of day.
If you absolutely indispensably need an old-fashioned java.util.Date object for a legacy API that you cannot change, here’s one easy way to get one. It may not work as desired, it may not give you exactly the date that you need, it depends on your exact requirements.
YearMonth expiration = YearMonth.of(2021, 8); // or .of(2021, Month.AUGUST);
Date oldFashionedDateObject = Date.from(expiration
.atDay(1)
.atStartOfDay(ZoneId.systemDefault())
.toInstant());
System.out.println(oldFashionedDateObject);
On my computer this prints
Sun Aug 01 00:00:00 CEST 2021
What we got is the first of the month at midnight in my local time zone — more precisely, my JVM’s time zone setting. This is one good guess at what your legacy API expects, but it is also dangerous. The JVM’s time zone setting may be changed under our feet by other parts of the program or by other programs running in the same JVM. In other words, we cannot really be sure what we get.
The time zone issue gets even worse if the date is transmitted to a computer running a different time zone, like from client to server or vice versa, or to a database running its own time zone. There’s about 50 % risk that your Date will come through as a time in the previous month.
If you know the time zone required in the end, it will help to specify for example ZoneId.of("America/New_York") instead of the system default in the above snippet.
If your API is lenient and just needs some point within the correct month, you’ll be better off giving it the 2nd of the month UTC or the 3rd of the month in your own time zone. Here’s how to do the former:
Date oldFashionedDateObject = Date.from(expiration
.atDay(2)
.atStartOfDay(ZoneOffset.UTC)
.toInstant());

Require help for SWT DateTime in Java

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

Calculating a day given a Date

From a given Date I need to calculate midnight of its day. Here's what I came up with. It's so ugly that I figure there must be a better way.
private Date day(Date creation) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(creation);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
return calendar.getTime();
}
Suggestions?
Kent
You should consider the built-in date API obselete. Instead use the Joda date and time API.
Here's a drop-in replacement for your method.
private Date day(Date creation) {
return new DateMidnight(creation).toDate();
}
Here's a simple test:
public static void main(String[] args) {
final Date creation = new Date();
final Date midnight = new Foobar().day(creation);
System.out.println("creation = " + creation);
System.out.println("midnight = " + midnight);
}
The output is:
creation = Sun May 31 10:09:38 CEST 2009
midnight = Sun May 31 00:00:00 CEST 2009
JODA might have a better solution, at the cost of another dependency on a library. I'm looking at its DateMidnight property. I'm sorry that I can't answer more authoritatively, but I'm not a JODA user myself.
If you're looking for local time, that's the best you're going to get. And although you may consider it ugly, there's (potentially) a lot going on behind the scenes.
If you want midnight UTC, the following will work:
public static void main(String[] argv)
throws Exception
{
final long MILLIS_PER_DAY = 24 * 3600 * 1000L;
long midnightUTC = (System.currentTimeMillis() / MILLIS_PER_DAY) * MILLIS_PER_DAY;
}
Edit: I really don't recommend using local dates in "production" code. They cause more trouble than they're worth -- consider a person on the US west coast who suddenly finds his/her "day" trimmed by 3 hours because an east coast computer has a different idea of midnight.
JODA is the way to go if you have serious calendar needs, at least until JSR-310 gets into the JDK (1.7 maybe, if not 1.8).
That being said, there are a couple of things that could be done to make this code a little nicer.
import static java.util.Calendar.*;
...
private static final List<Integer> TIME_FIELDS =
Arrays.asList(HOUR_OF_DAY, MINUTE, SECOND, MILLISECOND);
private Date day(Date creation) {
Calendar c = getInstance();
c.setTime(creation);
for(int field : TIME_FIELDS) c.set(field, 0);
return c.getTime();
}
That won't win any performance awards. You could do a standard for loop relying on the specific field values (the Calendar class has a FIELD_COUNT field kind of implying you can do something like that) but that risks issues across JDK implementations and between versions.
Using the date4j library :
DateTime start = dt.getStartOfDay();
I think the only way you're going to make this code significantly better is by a change in representation. For example,
Represent the day by the "absolute date" system explained by Nachum Dershowitz and Ed Reingold in Calendrical
Calculations.
Represent the time by counting seconds from midnight. Or if you need sub-second resolution, count milliseconds.
From your brief example I can't tell at what points in your program you need to be compatible with existing Date and Calendar classes, or if you can create a useful subclass using a saner representation.
Haven't programmed Java in a while, but you might be able to call this set method passing in the current values for year, month, and day. Although from reading a little close, you may have to call clear first. This may or may not be less verbose than using your current method.
This is just the complement of the originally posted code. It sets the Year, Month, and Day in a new GregorianCalendar object, instead of clearing everything but the Year, Month, and Day in the calendar variable. It's not much of an improvement, but I think it's clearer to say which fields you are copying, instead of which fields you're ignoring.
public Date day(Date creation) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(creation);
return new GregorianCalendar(
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH)).getTime();
}
Personally, I think I'd go with the Joda library proposed by others.

Categories