This question already has answers here:
java.util.Date format conversion yyyy-mm-dd to mm-dd-yyyy
(8 answers)
Closed 5 years ago.
I am trying to change the format of Date objects, I am trying to do it in this way:
for(Date date : dates){
DateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
String formatterDate = formatter.format(date);
Date d = formatter.parse(formatter.format(date));
}
But this does not have any effect on the d object, it is still with the old format, can't really understand why it is like that.
Please try to keep two concepts apart: your data and the presentation of the data to your user (or formatting for other purposes like inclusion in JSON). An int holding the value 7 can be presented as (formatted into) 7, 07, 007 or +7 while still just holding the same value without any formatting information — the formatting lies outside the int. Just the same, a Date holds a point in time, it can be presented as (formatted into) “June 1st 2017, 12:46:01.169”, “2017/06/01” or “1 Jun 2017” while still just holding the same value without any formatting information — the formatting lies outside the Date.
Depending on your requirements, one option is you store your date as a Date (or better, an instance of one of the modern date and time classes like LocalDate) and keep a formatter around so you can format it every time you need to show it to the user. If this won’t work and you need to store the date in a specific format, then store it as a String.
Java 8 (7, 6) date and time API
Now I have been ranting about using the newer Java date and time classes in the comments, so it might be unfair not to show you that they work. The question tries to format as yyyy-MM-dd, which we may do with the following piece of code.
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("uuuu/MM/dd");
for (LocalDate date : localDates) {
String formatterDate = date.format(dateFormatter);
System.out.println(formatterDate);
}
In one run I got
2017/05/23
2017/06/01
Should your objects in the list have other types than LocalDate, most other newer date and time types can be formatted in exactly the same way using the same DateTimeFormatter. Instant is a little special in this respect because it doesn’t contain a date, but you may do for example myInstant.atZone(ZoneId.of("Europe/Oslo")).format(dateFormatter) to obtain the date it was/will be in Oslo’s time zone at that instant.
The modern classes were introduced in Java 8 and are enhanced a bit in Java 9. They have been backported to Java 6 and 7 in the ThreeTen Backport with a special edition for Android, ThreeTenABP. So I really see no reason why you should not prefer to use them in your own code.
Try this one.
String formattedDate = null;
SimpleDateFormat sdf = new SimpleDateFormat(format you want);
formattedDate = sdf.format( the date you want to format );
return formattedDate;
some not best solution, but it works: this method will convert Date object to String of any pattern you need
public static void format(Date date){
String pattern = "MMM d yyyy";
LocalDateTime localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
String result = formatter.format(localDate);
// new Date() -> Jun 1 2017
}
SimpleDateFormat is useful while converting Date to String or vice-versa. java.util.Date format will always remain same. If you want to display it in standalone application then use date.getxxx() methods and choose your design.
Related
This question already has answers here:
How to reduce one month from current date and stored in date variable using java?
(8 answers)
Closed 1 year ago.
I need to get the date today, and the date one month ago in the format yyyy-mm-dd
To get the date today i have:
val todaysDate = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(Date()).toString()
Which works as i want:
2021-05-12
However i cannot figure out how to get the date for one month ago in the same format.
I found this function in another thread but it returns "Mon Apr 12 18:24:37 GMT+02:00 2021"
fun getDaysAgo(daysAgo: Int): Date {
val calendar = Calendar.getInstance()
calendar.add(Calendar.DAY_OF_YEAR, -daysAgo)
return calendar.time
}
How can i get the date one month ago in the same format? Thanks.
Edit:
The solution for me was actually very simple using the getDaysAgo function
var daysAgo= SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(getDaysAgo(30)).toString()
However Ole's answer below is probably better and the recommended way. Did not work for me as it requires api level 26 (android) and im on 23.
LocalDate from java.time
Keep and process dates as LocalDate objects, not as strings.
Only when you need to give string output, format your LocalDate into a string in the appropriate format.
Like many in the comments I recommend that you use java.time, the modern Java date and time API, for your date work. In Java code, still keeping processing and formatting separate and trusting you to translate to Kotlin yourself:
public static LocalDate get1MonthAgo() {
return LocalDate.now(ZoneId.systemDefault()).minusMonths(1);
}
public static String formatToIso8601(LocalDate date) {
return date.toString();
}
Assuming that you need to output the date 1 month ago as a string, use the two methods like this:
LocalDate oneMonthAgo = get1MonthAgo();
String oneMonthAgoFormatted = formatToIso8601(oneMonthAgo);
System.out.println(oneMonthAgoFormatted);
When I ran this evening in my time zone, the output was:
2021-04-12
I am exploiting the facts that the format you asked for is ISO 8601, the international format, and that LocalDate (and also the other date-time classes of java.time) produce(s) ISO 8601 format from their toString methods. So we need to specify no formatter. Which is good because fiddling with a format pattern string is always error-prone.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Wikipedia article: ISO 8601
I wanted to convert date in yymmdd format to YYYYMMDD, but when using the simpledateformat class i am getting the years after 1970, but the requirement is of the year which is prior to 1970.
java.time
Parsing input
The way to control the interpretation of the 2-digit year in yymmdd is through the appendValueReduced method of DateTimeFormatterBuilder.
DateTimeFormatter twoDigitFormatter = new DateTimeFormatterBuilder()
.appendValueReduced(ChronoField.YEAR, 2, 2, 1870)
.appendPattern("MMdd")
.toFormatter();
String exampleInput = "691129";
LocalDate date = LocalDate.parse(exampleInput, twoDigitFormatter);
Supplying a base year of 1870 causes two-digit years to be interpreted in the range 1870 through 1969 (so always prior to 1970). Supply a different base year according to your requirements. Also unless you are sure that input years all across a period of 100 years are expected and valid, I recommend you do a range check of the parsed date.
Formatting and printing output
DateTimeFormatter fourDigitFormatter = DateTimeFormatter.ofPattern("uuuuMMdd");
String result = date.format(fourDigitFormatter);
System.out.println(result);
Output in this example is:
19691129
If instead input was 700114, output is:
18700114
Use LocalDate for keeping your date
Instead of converting your date from one string format to another, I suggest that it’s better to keep your date in a LocalDate, not a string (just like you don’t keep an integer value in a string). When your program accepts string input, parse into a LocalDate at once. Only when it needs to give string output, format the LocalDate back into a string. For this reason I have also separated parsing from formatting above.
Link
Oracle tutorial: Date Time explaining how to use java.time.
This question already has answers here:
How to get start and end range from list of timestamps?
(2 answers)
Date year value showing valid when invalid [duplicate]
(3 answers)
Closed 4 years ago.
I'm in the process of changing our existing SimpleDateFormat based code to use the new Java 8 LocalDateTime and ZonedDateTime classes.
I couldn't find an easy way to convert this piece.
Considering sample date and format.
String testDate = "2012-12-31T10:10:10-06:00";
String testFormat = "yyyy-MM-dd'T'HH:mm:ss";
Existing code,
SimpleDateFormat sdf = new SimpleDateFormat(testFormat);
System.out.println(sdf.parse(testDate));
This piece works for both the date value containing timezone offset like mentioned above or not. It ignores the timezone if provided and in both cases defaults to the system timezone.
However if I replace it with below code,
DateTimeFormatter df = DateTimeFormatter.ofPattern(testFormat);
LocalDateTime ldt = LocalDateTime.parse(testDate, df);
ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault());
System.out.println(zdt.toString());
It fails for the above format. To get it to work, I have to get rid of the timezone bit in the date i.e. convert it to "2012-12-31T10:10:10" or then change the format to include timezone details i.e. 'z'.
So from my initial tests at least it seems the new classes are pretty strict from matching the format to the T unlike SimpleDateFormat. I even tried marking the DateTimeFormater.setLineant(), but that too didn't help. Or maybe there are some other classes which can work in this case, just that I am not aware of them.
To add more details as why i want to have the legacy behavior using the new API's. In our product we expose these API's which end customer can use, so the API in question accepts both the datetime value in string and the format and used "SimpleDateFormat". So i want existing behavior to continue even with the new API's just so that we continue to maintain backward compatibility.
For now the only solution for above example i have come up with is handle it as an exception case,
DateTimeFormatter df = DateTimeFormatter.ofPattern(testFormat);
LocalDateTime ldt = null;
try {
ldt = LocalDateTime.parse(testDate, df);
} catch (DateTimeParseException dtpException) {
ldt = ZonedDateTime.parse(testDate).toLocalDateTime();
}
if (ldt != null) zdt = ldt.atZone(ZoneId.systemDefault());
Can someone share some pointers around this use case?
This question already has answers here:
Java Date changing format [duplicate]
(4 answers)
java.util.Date format conversion yyyy-mm-dd to mm-dd-yyyy
(8 answers)
Closed 5 years ago.
I'm trying to get the current day's date at 6 am in the format yyyy-MM-dd HH:mm:ss, but it shows as : Wed Dec 20 06:00:00 CST 2017
This is my code:
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd 06:00:00");
Date date0 = new Date();
String x = dateFormat.format(date0);
try{
DateFormat formatter ;
Date date ;
formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
date = formatter.parse(x);
}
catch (Exception e){}
java.util.Date is a container for the number of milliseconds since the Unix Epoch, it doesn't not maintain any kind of internal formatting concept, instead, when you print it, it use Date#toString which generally uses the current Locale to provide a human readable representation of the value.
While I'm sure you could continue to mess about with Date to make this work, a much simpler approach would be to take advantage of the newer Date/Time API, something like...
LocalDateTime now = LocalDateTime.now();
LocalDateTime then = now.withHour(6).withMinute(0).withSecond(0).withNano(0);
String formatted = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(then);
System.out.println(formatted);
Which, for me, prints out 2017-12-21 06:00:00
TL;DR
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
LocalDate date0 = LocalDate.now(ZoneId.of("America/Winnipeg"));
String at6Am = date0.atTime(LocalTime.of(6, 0)).format(formatter);
System.out.println(at6Am);
Running just now this printed
2017-12-21 06:00:00
Details
The classes that you use, Date and SimpleDateFormat, have been around since Java 1.0, some 20 years. They have proved to be poorly designed and cumbersome to use. Maybe for that reason too, much has been written about them, and from searching the web you could easily get the impression that these are the classes you should use. On the contrary, they are the classes you should avoid. Their replacement came out with Java 8, it will soon be 4 years ago.
Formatters are for formatting and parsing. You shouldn’t use a formatter, even less two formatters, for changing the time-of-day to 6 AM.
It is never the same date everywhere on the globe. So getting today’s date is an operation that depends on a time zone. I have made the time zone explicit in my code so the reader will also be aware of this fact. Please substitute your desired time zone if it didn’t happen to be America/Winnipeg.
You are modifying existing software. If you got an old-fashioned Date object from it, first convert it to the modern Instant type, then use the modern API for further operations. For example:
Date date0 = getOldfashionedDateFromLegacyApi();
String at6Am = date0.toInstant()
.atZone(ZoneId.of("America/Winnipeg"))
.with(LocalTime.of(6, 0))
.format(formatter);
What went wrong in your code?
I don’t think there’s anything really wrong with the code in your question. You wanted your date-time formatted as 2017-12-20 06:00:00, and you got that in the string x in the third code line. Be happy with that and leave out the remainder of the code.
There is no such thing as imposing the format on the date-time objects, (no matter if we talk the outdated or the modern API). Formatting a date-time means converting it to a String in the desired format.
After parsing, you need to format it as follows: formatter.format(date). So modify your code as follows:
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd 06:00:00");
Date date0 = new Date();
String x = dateFormat.format(date0);
try{
DateFormat formatter ;
Date date ;
formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
date = formatter.format(formatter.parse(x));
}
catch (Exception e){}
I have a timestamp field of Oracle in Java String
String strDate = "24.12.12 03:30:00,000"; //Timestamp field of Oracle
I need to convert it to Java.util.Date.
Please tell me a way to do this.
Note: I don't have first two digits for the year, how can java understand that this is year 1912 or 2012 and so on.
The class you want is SimpleDateFormat. You'll create a pattern that matches your expected input, and parse it. Here's an example, though it may be incorrect in some places (I used 0-23 hour, maybe you want 1-24, etc.)
String strDate = "24.12.12 03:30:00,000";
SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yy HH:mm:ss,SSS");
Date date = sdf.parse(strDate);
Regarding your 1912 vs 2012 problem, Java will make some assumptions when there are only 2 digits. Specifically:
For parsing with the abbreviated year pattern ("y" or "yy"),
SimpleDateFormat must interpret the abbreviated year relative to some
century. It does this by adjusting dates to be within 80 years before
and 20 years after the time the SimpleDateFormat instance is created.