Not able to work with Java Date Function properly - java

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.

Related

Format a XMLGregorianCalendar with Italian date format(dd/mm/yyyy) with no time [duplicate]

This question already has answers here:
want current date and time in "dd/MM/yyyy HH:mm:ss.SS" format
(11 answers)
Closed 4 years ago.
I am trying to convert a java.util.Date to XMLGregorianCalendar in Italian format (dd/mm/yyyy) with no time. Whatever I try the output always prints yyyy-mm-dd.
GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("Europe/Rome"));
XMLGregorianCalendar xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendarDate(cal.get(Calendar.YEAR),
cal.get(Calendar.MONTH)+1, cal.get(Calendar.DAY_OF_MONTH),
DatatypeConstants.FIELD_UNDEFINED);
System.out.println(xmlDate);
I am a consumer of SOAP web-service, and the date attribute is defined as XMLGregorianCalendar.
Please advise how can I change the code to get the output with format (dd/mm/yyyy).
You don’t need an XMLGregorianCalender. It will not, cannot give you what you ask for. Instead you need a LocalDate and a DateTimeFormatter:
DateTimeFormatter italianDateFormatter
= DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)
.withLocale(Locale.ITALIAN);
LocalDate date = LocalDate.now(ZoneId.of("Europe/Rome"));
String formattedDate = date.format(italianDateFormatter);
System.out.println(formattedDate);
When I ran this code today, the output was:
21/01/19
The difference from what you ask for is the two digit year, 19. If instead of FormatStyle.SHORT we use FormatStyle.MEDIUM, we get four digit year, but the month as a three letter abbreviaiton:
21-gen-2019
The advantage is that the code lends itself very well to internationalization: you just need to change the locale to get proper code for some other language and country. If you do need 21/01/2019 (with four digit year), specify the format explicitly using a pattern:
DateTimeFormatter italianDateFormatter
= DateTimeFormatter.ofPattern("dd/MM/uuuu");
21/01/2019
What’s wrong with using XMLGregorianCalendar?
When you call System.out.println(xmlDate), you are implicitly calling toString on your XMLGregorianCalendar. When it hasn’t got time and zone offset, toString always generates yyyy-MM-dd format, there is no way you can change that. On the other hand you can have any format you like in a String. Next obstacle is, there is no formatter that can format an XMLGregorianCalendar directly. You would need to convert to a different type, like ZonedDateTime, for example, first. Since you only want the date, neither the time of day nor the time zone, it’s simpler and easier to start out from LocalDate from the start. Not least for those reading and maintaining your code after you.
Your question mentions java.util.Date and your code uses GregorianCalendar too. Both of those classes are poorly designed and long outdated, fully replaced by java.time, the modern Java date and time API. So I suggest you don’t use them.
Link
Oracle tutorial: Date Time explaining how to use java.time, the modern Java date and time API.

Java how to remove nth minute from given time string without considering time zone

I tried to remove minute from given time, but some how it is converting time to my local time zone
String timeStamp="20180623 05:58:15" ;
dateFormat inputFormatter = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
Date date = inputFormatter.parse(timeStamp);
date.setMinutes(-2);
logger.info("Before converting : "+date);
DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
Here it is converting to my local time and subtracting 2 minutes from given time, but I don`t want to check the time zone here instead, what ever time I give it should just subtract 2 minutes.
Start with understanding into how Date works. When you do...
logger.info("Before converting : "+date);
The Date class uses it's toString method to format the the date/time information represented by the Date class into a human readable format. It doesn't "convert" the date/time value in anyway
So taking your code from above (and reworking it so it works), it outputs...
Before converting : Sat Jun 23 04:58:15 AEST 2018
20180623 04:58:15
on my machine - why are the values the same? Because the input doesn't have any time zone information, so the time is likely been treated as been in the machines local timezone (and the value is simply been formatted for output).
Date is just a container for the number of milliseconds since the Unix Epoch, it's format agnostic - meaning it carries not formatting information.
Date is also effectively deprecated - not to mention that setDate is also very much deprecated
A better (starting point) overall is to make use the newer date/time API introduced in Java 8 (and which has back port support for earlier versions of the API)
String timeStamp = "20180623 05:58:15";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss", Locale.ENGLISH);
LocalDateTime ldt = LocalDateTime.parse(timeStamp, formatter);
ldt = ldt.minusMinutes(2);
System.out.println(ldt);
System.out.println(ldt.format(formatter));
This will output...
2018-06-23T05:56:15
20180623 05:56:15
The input and the output are still consider as been in the machines local time zone.
but I don`t want to check the time zone here instead, what ever time I give it should just subtract 2 minutes
Just remember, the API still needs to have some concept of time zone, weather it's the local time zone or UTC/GMT, but since your input doesn't provide any kind of information, you need to make a choice over "how" best to handle that issue. The example above just "assumes" local time, but you could use ZonedDateTime and convert it to "common" time zone from which your operations are executed or, better yet, make all your strings carry time zone information
Oh, and for the love of my sanity, stop managing date/time values in String format - get them into an appropriate container as soon as possible and manage them from there - I've spent a week wrangling inappropriately formatted date strings and I'm not happy Jan, not happy

How to print the current time and date in ISO date format in java?

I am supposed to send the current date and time in ISO format as given below:
'2018-02-09T13:30:00.000-05:00'
I have written the following code:
Date date = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm");
SimpleDateFormat formatter1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.000'Z'");
System.out.println(formatter.format(date));
System.out.println(formatter1.format(date));
It prints in the following way:
2018-04-30T12:02
2018-04-30T12:02:58.000Z
But it is not printing as the format mentioned above. How can I get the -5:00 as shown in the format and what does it indicate?
In java 8 you can use the new java.time api:
OffsetDateTime now = OffsetDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE_TIME;
System.out.println(formatter.format(now)); // e.g. 2018-04-30T08:43:41.4746758+02:00
The above uses the standard ISO data time formatter. You can also truncate to milliseconds with:
OffsetDateTime now = OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS);
Which yields something like (only 3 digits after the dot):
2018-04-30T08:54:54.238+02:00
Easy solution:
System.out.println(OffsetDateTime.now(ZoneId.of("America/Panama")).toString());
Just now I got this output:
2018-04-30T02:12:46.442185-05:00
To control that seconds are always printed with exactly three decimals:
DateTimeFormatter formatter
= DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSXXX");
OffsetDateTime now = OffsetDateTime.now(ZoneId.of("America/Panama"));
System.out.println(now.format(formatter));
2018-04-30T02:12:46.442-05:00
The first, the easy version will print enough groups of three decimals to render the full precision. It will also leave out the seconds completely if they happen to be 0.0. Both are probably OK because all of this is allowed within the ISO 8601 format that you asked for. So whoever receives the string should be happy anyway.
Please fill in your desired time zone where I used America/Panama. It’s best to give explicit time zone for predictable output.
I am using and recommending java.time, the modern Java date and time API. The SimpleDateFormat that you used is not only long outdated, it is also notoriously troublesome. java.time is so much nicer to work with.
What does -05:00 indicate?
-05:00 is an offset from UTC (or GMT, it is nearly the same thing). So your example string is probably from eastern time zone in North America or some other place in Central or Southern America (Cuba, Bolivia, to mention a few that use this offset for some of the year). More precisely -05:00 means that we’re using a clock that is 5 hours (and 0 minutes) behind UTC. So 2:12:46-05:00 denotes the same point in time as 7:12:46 UTC. If we only knew the time was 2:12:46 and didn’t know a time zone or offset, it would be very ambiguous. An offset is perfect for turning the time into an unambiguous point in time.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Wikipedia article: ISO 8601
Wikipedia article: UTC offset

SimpleDateFormat issue when parsing a String in ISO 8601 format

Appreciate there are lots of similar posts on this but I couldn't find a specific one to help.
I'm trying to convert this string to a Date in Java
2017-05-16 06:24:36-0700
But it fails each time with this code
Date Login = new SimpleDateFormat("dd/MM/yy HH:mm:ss").parse("2017-05-16 06:24:36-0700");
Now I'm presuming its due to the timezone info at the end - I just can't figure out how to set the format. I tried this but no luck
SimpleDateFormat("dd/MM/yy HH:mm:ssZ")
Any ideas?
The date format passed to your SimpleDateFormat is "dd/MM/yy", while the date you are trying to parse is of the format "yyyy-MM-dd". Try this instead:
Date login = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssZ").parse("2017-05-16 06:24:36-0700");
As a side note, depending on which version of Java you are using, I would recommend using the new java.time package (JDK 1.8+) or the back port of that package (JDK 1.6+) instead of the outdated (no pun intended) Date and/or Calendar classes.
Instant login = Instant.from(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ssZ").parse("2017-05-16 06:24:36-0700"));
I have already upvoted Bryan’s answer exactly because it includes and recommends the java.time solution. I need to add a few thoughts, though.
Your code, reviloSlater, throws away the time zone information (more precsely, zone offset information), I’m not sure I would dare do that from the outset. With java.time classes it’s more natural to include it, and it’s easy to discard at a later point when we are sure we don’t need it.
To parse with offset:
OffsetDateTime loginOdt = OffsetDateTime.parse("2017-05-16 06:24:36-0700",
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ssZ"));
To drop the time zone offset information
LocalDateTime loginLdt = loginOdt.toLocalDateTime();
A LocalDateTime is a date and a time without any time zone or offset information. In this case of course we get
2017-05-16T06:24:36
Bryan’s java.time code too uses the time zone offset information from the string. Edit: after Bryan’s edit that code now works and gives us:
2017-05-16T13:24:36Z
This is the same point in time (Instant.toString() prints the time in UTC). Another way is, with the OffsetDateTime from before we can just do
Instant login = loginOdt.toInstant();
java.time is loaded with possibilities.

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());

Categories