Somehow I am being reported a issue, in which following code provides date in future.
The timezone used is GMT+01:00.
The numberOfDays is non negative integer.
The intention of this code is reduce the number of days from current date.
SimpleDateFormat formatter = new SimpleDateFormat("dd MMM yy",Locale.ENGLISH);
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DAY_OF_MONTH, -numberOfDays);
Date date = calendar.getTime();
String dateStr= formatter.format(date);
System.out.println("Date : "+dateStr);
I am not able to reproduce this on my machine.
Does the Locale affect the TimeZone?
I tried to correlate to Why does a new SimpleDateFormat object contain calendar with the wrong year?, and Strange problem with timezone, calendar and SimpleDateFormat but in vain.
Please help me understand and rectify this issue.
Well, two possibilities I can think of off the top of my head:
The system date on the client machine is incorrect, so the calendar starts with a date in the future
If numberOfDays is negative, it will obviously push the date into the future
The Locale isn't directly related to the time zone - they're independent, although obviously a machine with a French locale is likely to be in a French time zone etc.
Personally I would avoid using Date/Calendar entirely and use Joda Time as a much nicer date and time API, but that wouldn't help with either of the ideas I gave above...
Related
If I take current date from my application, it comes with variation like below:
scenario 1: when the date is less than 10th of the month, a month is less than 10 of the year --> example: 5/9/18
scenario 2: when the date is >= 10th of the month, a month is less >= 10 of the year --> example: 10/11/18
Note: all the examples are in MM/DD/YY format and timezone is the USA
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DATE,-2);
DateFormat dateFormat = new SimpleDateFormat("MM/dd/yy HH:mm a");
String PastDate = dateFormat.format(cal.getTime());
info("Date is displayed as : "+ PastDate );
The above piece of code throwing me an error when the scenario 1 is in place. But if I format the date-time as "M/d/yy H:mm a" it works for both the scenario. I need the date add also.
Will it be a good practice to use the 2nd format? or there is any other way to get it done. Expert guidance please..
java.time
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT)
.withLocale(Locale.US);
ZonedDateTime dayBeforeYesterday = ZonedDateTime.now(ZoneId.of("America/St_Thomas"))
.minusDays(2);
System.out.println(dayBeforeYesterday.format(formatter));
Running just now I got this output:
5/7/18, 8:44 AM
Please specify your desired time zone where I put America/St_Thomas. Think twice before you use ZoneId.systemDefault() for your JVM’s time zone setting since this setting may be changed at any time from other parts of your program or other programs running in the same JVM; but if you trust the setting reflects the user’s time zone, it’s the correct thing to use.
Rather than defining your own output format prefer using one of the built-in formats you get from DateTimeFormatter.ofLocalizedDateTime. Do specify locale (no matter if you use a built-in format or roll your own). Again, use Locale.getDefault() if you trust the JVM’s setting is correct.
Avoid the old date and time classes like Calendar, DateFormat and SimpleDateFormat. They are not only long outdated, they are also poorly designed and the last two in particular notoriously troublesome. Today we have so much better in java.time, the modern Java date and time API.
Link: Oracle tutorial: Date Time explaining how to use java.time.
The number of characters in the format MM indicates that two digits are required in the input. A single character M will match one or two digits. Use M/d/yy H:mm a to support your desired formats.
I ma getting exeception while parsing the date.
following is the code:
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-DD");
Date d = format.parse("2014/02/20");
System.out.println(d);
Not only have you got the slashes/dashes wrong, you're also using DD (day of year) instead of dd (day of month). You want:
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
As always, read the documentation to find out exactly what pattern symbols mean - and if you find it's behaving oddly, check the pattern against the data very carefully.
I would also recommend:
Using Joda Time (pre-Java-8) or java.time (Java 8) if you possibly can; the java.util.Date/Calendar API is horrible
Specifying the locale explicitly
Specifying the time zone explicitly
Currently you're using the default time zone and locale. While the locale may not matter in this case (unless it's used to pick the calendar system; I can't remember offhand) I think it's clearer to explicitly specify it. The time zone definitely matters; if you only ever want to treat this as a date (no time) it's probably worth specifying UTC - that way it's easy to interoperate with anything else, and you get day boundaries in obvious places in the underlying millisecond representation.
Your dateformat doesn't match your string.
Date d = format.parse("2014-02-20");
or
SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd");
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());
Hi i have problem with simpledateformat+ timezone here is my code and i am expecting my output as 25/11/2011 but its returning as 24/11/2011. And my current time zone is Pacific and i am testing this on (25/11/2011).
Please help.
Hi Please find the complete program i am not just printing it i am comparing with current date and i was expecting the output as False but its going to True.
This is the typical scenario happening in production also servers are located in Pacific and users are from London. Please provide me the solutions for this problem.
String vacationStartDate = "25/11/2011";
SimpleDateFormat dateFormatter = new SimpleDateFormat("dd/MM/yyyy");
//America/Los_Angeles
TimeZone tz = TimeZone.getTimeZone("Europe/London");
dateFormatter.setLenient(false);
dateFormatter.setTimeZone(tz);
Date start = dateFormatter.parse(vacationStartDate);
Date todayBeginning = new Date();
if ( start.before(todayBeginning)){
System.out.println("True ");
} else {
System.out.println("False ");
}
This is because you're parsing the date in the London timezone, but printing it out in your timezone. So 25/11/2011 00:00:00 in London is 24/11/2011 16:00:00 or whatever in your timezone.
Your code returns the current date of your Timezone, so the output is correct. Please note that the TimeZone.getTimeZone("Europe/London"); is the timezone of the Date being parsed so the date returned given that your current timezone is Pacific will be before the London date.
A date (day/month/year) is a fundamentally different concept than a instant of time (when we say "vacations start on 25/11/2011" we are not meaning "25/11/2011 at 00:00:00", we are refering to that day as a whole entity). It's a disgrace that the standard Java API (as many others) confuses this concepts, and your problem (explained in Matthew Farwell's answer) is one of the many absurd issues that this confusion causes: one should not need to deal with timezones issues when doing pure dates calculation.
Consider using Joda time, which has an specific class (Localdate) for pure dates.
I know there are other similar questions to this, but I came up with my own way of getting the current time in a specific time zone, so I just wanted to confirm if it is correct or not, or there are gotchas I didn't take care of.
Calendar cal = Calendar.getInstance();
// Assuming we want to get the current time in GMT.
TimeZone tz = TimeZone.getTimeZone("GMT");
cal.setTimeInMillis(calendar.getTimeInMillis()
+ tz.getOffset(calendar.getTimeInMillis())
- TimeZone.getDefault().getOffset(calendar.getTimeInMillis()));
// Calendar should now be in GMT.
Is the above correct at all? I did my own test and it seemed to be working as expected, but just wanted to confirm it again with the experts in Stack Overflow.
If you simply do a Calendar.getInstance with the TimeZone argument, the calendar's internal state for the get() methods will return you the field with the time for that timezone. For example:
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
// if i run this at 9 EST this will print 2
System.out.println(cal.get(Calendar.HOUR));
If you just need the local time for display purposes, you can set the TimeZone on your format object. For example:
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss z");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(sdf.format(new Date()));
Like Macarse said though, Joda time is where it's at if you need to do anything more complex. The Java date APIs are a nightmare.
I'd prefer using joda-time instead of that.
Check this link.