why Date object returns wrong day? - java

I am doing this..
String dateString = "12 Nov 2011 12:00"
DateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm");
Date date = formatter.parse(dateString);
System.out.println(date.getDay());
this prints out day as 3 ? why is this happening ? how can I print the correct day?

Please read the documentation it is worth learning by that.
date.getDay() prints the day of the week. It should display 6 as that is a saturday, not sure how you got 3 as the result.

date.getDay() returns the day of the week as a zero-indexed numeric. In this case it should be Saturday (6).
Your result of Wednesday (3) suggests you are using a variation of the provided code and perhaps forgotten that the month is zero-indexed. e.g.
Date date = new Date(2011, 11, 12, 24, 0, 0); // month is now December, and time ticks over to Wednesday 13th
System.out.println(date.getDay()); // this would produce 3
I believe you want date.getDate().
If you are looking for a String representation of the day, take a look at this example:
http://www.java-examples.com/formatting-day-week-using-simpledateformat
Even better, check out the Joda-Time library, it is much more intuitive than the classes provided in the Java SDK. A future version of Java may even adopt a new date framework similar to Joda-Time (JSR-310)

The code you showed should print 6, as this date is a Saturday. On my computer that happens. without further information I cannot deduce more. Is this the complete code you execute? You could print the value of date.toString(), that would possibly give some more information.

Related

Java DateTimeFormatter issue [duplicate]

This question already has answers here:
Why does Java's java.time.format.DateTimeFormatter#format(LocalDateTime) add a year?
(2 answers)
Using DateTimeFormatter on january first cause an invalid year value
(1 answer)
Closed 1 year ago.
The following code (in main)
LocalDate d ;
DateTimeFormatter formatter;
d = LocalDate.of(2021, 11, 14);
System.out.println(d);
formatter = DateTimeFormatter.ofPattern("MM.dd.YYYY");
System.out.println(formatter.format(d));
formatter = DateTimeFormatter.ofPattern("YYYY/MM/dd");
System.out.println(formatter.format(d)+ "\n");
d = LocalDate.of(2021, 1, 1);
System.out.println(d);
formatter = DateTimeFormatter.ofPattern("MM.dd.YYYY");
System.out.println(formatter.format(d));
formatter = DateTimeFormatter.ofPattern("YYYY/MM/dd");
System.out.println(formatter.format(d));
outputs in my Netbeans 12.5 with the latest or fairly recent Oracle Java 17
run:
2021-11-14
14.11.2021
2021/11/14
2021-01-01
01.01.2020
2020/01/01
BUILD SUCCESSFUL (total time: 0 seconds)
The formatted output for today, 14-NOV-2021, is ok, but output for 01-JAN-2021 is wrong. Formatted output prints 2020 , one year off.
Can you repeat this? If so: Any ideas why this happens?
According to the Javadoc of java.time.format.DateTimeFormatter
y (lowercase) represents the year-of-era and
Y (uppercase) represents the week-based-year.
The week-based date/time system is defined in ISO 8601 (see: Wikipedia article).
You want u, not Y:
Y is week-based year. If you're an accountant, this is important. If you're not, this is the devil: It seems right almost always, except in certain highly exotic dates, such as jan 1st. Weeks customarily are defined as: "Whatever year it is on the thursday of that week, that's the year that week belongs to", so if e.g. Jan 1st falls on a friday, then the week that contains Jan 1st is of the previous year (as the thursday of that week was dec 31st).
y is year as you mostly know it, except it doesn't really do what you want when go to BC years. It's not likely to come up, but then neither is the week-based-year thing. Nobody likes Year-2k style bugs, right?
u truly does what you imagined. It just gives you the year. Negative if need be.

Calling getTime changes Calendar value

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

Getting wrong date when I add months

I am writing my stubs in StubbyDB. And asserting the data in functional tests. This is something I am doing in my functional tests to calculate date for assertion (using joda datetime library)
DateTime now = DateTime.now();
DateTime future = now.plusMonths(6);
And this is something I am doing in my stubs;
{{TODAY+6m}}
But I am getting the difference of few days. Is this the bug or am I doing something wrong?
Edit
Consider today is "30 Sept 2016", and I add 5 months to it then
now.plusMonths(5) => 2017-02-28
{{TODAY+5m}} => 2017-03-02
Reason
As per joda-time documentation,
2007-03-31 plus one month cannot result in 2007-04-31, so the day of
month is adjusted to 2007-04-30.
However StubbyDB use javascript based date calculation which adjust date 2007-04-31 to 2007-05-01.
So this is not the bug but this is how these APIs work.
Solution
Found in sample application
use {{JODA_TODAY+6m}} instead of {{TODAY+6m}}
if you start with 30/09/2016 and add five months you get 30/02/2017.
But February only has 28 days.
It looks like Jodatime has "rounded down" to give you the maximum valid date for the month (i.e 28th Feb) whereas the other library/code is treating "30th Feb" as 2nd March (since that is technically two days past the 28th, which the 30th would also be).
Both are valid assumptions for handling dates IMHO and are a good lesson in why date handling is hard. You'll need to be explicit about which convention you want to follow and you may have to code your assertions to follow Jodatime's conventions.
See: DateTime::plusMonths(int)
Returns a copy of this datetime plus the specified number of months.
The calculation will do its best to only change the month field
retaining the same day of month. However, in certain circumstances, it
may be necessary to alter smaller fields. For example, 2007-03-31 plus
one month cannot result in 2007-04-31, so the day of month is adjusted
to 2007-04-30.
So, 30 Sept 2016 + 5 months = 28 Feb 2017 (according to Joda's logic) and it is not a bug
Here is sample code for adding months to given calendar date
public class Demo {
// create a calendar
Calendar cal = Calendar.getInstance()
// print current date
System.out.println("The current date is : " + cal.getTime());
// add 1 months from the calendar
cal.add(Calendar.MONTH, 1);
}
FYR How to add one month to a date and get the same day

java parsing string to date

I am trying to parse 14th March 2011 to a date in Java for a time converter application... I get 26th Dec 2010... Please help.
import java.util.*;
import java.text.*;
class date {
public static void main(String[] args) {
try {
String timestampOrig = "11/03/14,15:00:00";
SimpleDateFormat inFormat = new SimpleDateFormat("YY/MM/dd','HH:mm:ss");
Date parseDate = inFormat.parse(timestampOrig);
System.out.println("parsed date: " + parseDate.toString());
}
catch(ParseException pe){
}
}
}
output:
parsed date: Sun Dec 26 15:00:00 EST 2010
YY should be yy (in lower case). You can find the list of available characters and their meaning in the documentation.
Out of curiosity, more information about YY, which is for week year, here (not 100% sure what it is to be honest).
java.time
I am providing the modern answer using java.time, the modern Java date and time API (since March 2014).
DateTimeFormatter inFormat = DateTimeFormatter.ofPattern("uu/MM/dd,HH:mm:ss");
String timestampOrig = "11/03/14,15:00:00";
LocalDateTime parsedDateTime = LocalDateTime.parse(timestampOrig, inFormat);
System.out.println("parsed date: " + parsedDateTime.toString());
Output is:
parsed date: 2011-03-14T15:00
I recommend you don’t use SimpleDateFormat and Date. Those classes are poorly designed and long outdated, the former in particular notoriously troublesome. Instead use LocalDateTime and DateTimeFormatter, both from java.time, the modern Java date and time API. The modern API is so much nicer to work with. And BTW would throw an exception if you tried with YY for year, which I find somewhat more helpful for catching your error.
The quotes around the comma in the format pattern string are optional. I know that the documentation recommends them, but I find the format pattern string more readable without them, so left them out.
What went wrong in your code?
Uppercase Y in the format patterns string is for week based year and only useful with a week number. Apperently SimpleDateFormat wasn’t able to combine your specified month and day of month with the week based year of 2011 and instead just took the first day of the week-based year (this is typical behaviour of SimpleDateFormat, giving you a result that cannot be but wrong and pretending all is well). Assuming your locale is American or similar, week 1 is the week that contains January 1 and begins on the Sunday of the same week, therefore in this case the last Sunday of the previous year, December 26, 2010.
With java.time you may use either lowercase y or u for year. The subtle difference is explained in the question linked to at the bottom. In any case a two-digit year is interpreted into the range from year 2000 through 2099 (there are ways to control the interpretation if you need to).
Links
Oracle tutorial: Date Time explaining how to use java.time.
Question: uuuu versus yyyy in DateTimeFormatter formatting pattern codes in Java?

Java - Subtract Days from date [duplicate]

This question already has answers here:
How to subtract n days from current date in java? [duplicate]
(5 answers)
Closed 7 years ago.
I'm trying to subtract 5 days from a date which comes in as a string initially.
I have had a look at some of the other posts on this subject but the result i get from the code is always incorrect. The main problem is that the year value does not seem to change when the days are subtracted for example - 2012-01-01 subtract 5 days gives me 'Jan 27 2012' using this code -
cal.add(Calendar.DATE, -5);
Please help.
Did you know that, in Java, month 1 is actually February?
Date februaryTheFirst = new Date(2012,1,1); // equals 2012-02-01
This might explain what you are seeing. If you want to instantiate 2012-01-01 instead, you should do:
Date firstDayOf2012 = new Date(2012,0,1); // this is 2012-01-01
Exactly the same thing happens when dealing with Calendar:
Calendar.getInstance().set(2012,0,1); // 2012-01-01
Be sure to check the documentation for Date(int, int, int) and Calendar.set(int, int, int). Also, you could check the way you are parsing the string. If you use SimpleDateFormat.parse(...), things can be easier.
Strange, isn't it? Go figure... Just as a fun fact, IntelliJ's documentation annotates this second parameter, month, with #MagicConstant, to remember the programmer that there's something very strange going on.
Calendar.FEBRUARY is 1 and five days before 1 Feb 2012 was 27 Jab 2012.
Your implementation is correct and you are getting the correct value aslo.
Calendar's Months started with 0
0 = Jan
1 = Feb
so subtracting 5 days from 2012-01-01 will definitely returns you Jan 27 2012
something is here also which will helps you Why is January month 0 in Java Calendar?
Joda-Time
The Joda-Time 2.7 library makes this work much easier. Just call the minusDays method.
String input = "2012-01-01";
DateTimeZone zone = DateTimeZone.forID( "America/Montreal" );
DateTime dateTime = new DateTime( input, zone );
DateTime then = now.minusDays( 5 );
DateTimeFormatter formatter = DateTimeFormat.forStyle( "FF" ).withZone( zone ).withLocale( Locale.CANADA_FRENCH );
String output = formatter.print( then );
If you want the beginning of the day, add a call to withTimeAtStartOfDay. This is unnecessary in your case, when parsing a date-only string with no time-of-day.
DateTime dateTimeAtStartOfDay = new DateTime( input, zone ).withTimeAtStartOfDay();
If you want only date without time-of-day or time zone, use LocalDate instead of DateTime.
LocalDate then = new LocalDate( "2012-01-01" ).minusDays( 5 );
If you need to convert to the old java.util.Date, call toDate on the DateTime.
java.time
Java 8 has a new package, java.time. These new classes were inspired by Joda-Time but were re-architected. Both java.time and Joda-Time can solve this particular problem equally well.
Use:
cal.add(Calendar.DAY_OF_MONTH, -5)
EDIT: sorry. DAY_OF_MONTH is a synonym to DATE. Instead of 1 use Calendar.JANUARY.
This a segment of code that is working on my pc. first you have to get the calendar instance the perform your calculation.
Calendar cal = Calendar.getInstance();
System.out.println("Today : " + cal.getTime());
// Subtract 300 days from the calendar
cal.add(Calendar.DATE, -300);
System.out.println("300 days ago: " + cal.getTime());
This is the output that you will get:
Today : Wed Oct 17 10:41:23 EET 2012
300 days ago: Thu Dec 22 10:41:23 EET 2011

Categories

Resources