SimpleDateFormat parsing results are odd - java

I want to parse dates from a filesystem and get them in this format:
2013-07-29 14:49:53.813588954 +0200
Therefore my pattern looks like this
yyyy-MM-dd HH:mm:ss.SSSSSSSSS Z
And finally my code:
String rawDate = "2013-07-29 14:49:53.813588954 +0200";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSSSSS Z");
Date date = sdf.parse(rawDate);
SimpleDateFormat out = new SimpleDateFormat("yyyy-MM-dd HH:mm");
String parsedDate = out.format(date);
System.out.println(rawDate + " -> " + parsedDate);
But my output looks like this:
2013-07-29 14:49:53.813588954 +0200 -> 2013-08-08 00:49:41.000000954 +0200
I even tried with setLenient(false) but then I got a ParseException.

You've parsed 813588954 as a number of milliseconds - that's over 9 days, and it's being added to 2013-07-29 14:49:53.
Basically, SimpleDateFormat doesn't handle parsing nanoseconds, and java.util.Date only supports millisecond precision anyway.
If you can possibly use Java 8, I'd recommend using java.time for everything - don't use java.util.Date at all. If you can use java.time for parsing but have to use java.util.Date for the rest, that will at least help.
If you can't use Java 8 at all, I'd suggest manually modifying the string to truncate the nanoseconds to milliseconds and then parse with SimpleDateFormat using a pattern that uses .SSS.

Parsing nanoseconds is supported by Java 8's DateTimeFormatter. For this you need to update your pattern:
String rawDate = "2013-07-29 14:49:53.813588954 +0200";
DateTimeFormatter rawDateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.nnnnnnnnn Z");
ZonedDateTime zonedDateTime = ZonedDateTime.parse(rawDate, rawDateFormatter);
System.out.println(zonedDateTime); // prints 2013-07-29T14:49:53.813588954+02:00
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
System.out.println(zonedDateTime.format(formatter)); // prints 2013-07-29 14:49

Because 53.813588954 means 53 seconds and 813588954 milliseconds and 813588954 milliseconds is around 9 days. When doing the formatting on your second output (i.e. parsedDate), Java automatically rounded up by the sequence of seconds -> minutes -> hours -> days -> months -> years.

Related

SimpleDateFormat sets current day for parsed date

Is there any way to use the following simpleDateFormat:
final SimpleDateFormat simpleDateFormatHour = new SimpleDateFormat("HH:mm:ss z");
and when invoking:
simpleDateFormat.parse("12:32:21 JST");
to return current date on the Date object?
For these example, it will return:
Thu Jan 01 05:32:21 EET 1970
and not:
<<today>> 05:32:21 EET <<currentYear>>
as I need.
No, SimpleDateFormat needs explicity the date in the input string. If you're using Java 8, you can go with a LocalDateTime:
LocalDateTime localDateTime = LocalDate.now().atTime(5, 32, 21);
If you want to include a time-zone, you can use ZonedDateTime.
Construct another SimpleDateFormat to print today's date:
String today = new SimpleDateFormat("yyyy/MM/dd").print(new Date());
(Be careful here: you might want to set the time zone on the SimpleDateFormat, as "today" is different in different time zones).
Update the date format to include year, month and day:
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss z");
And then prepend the date string with the date you want:
simpleDateFormat.parse(today + " " + "12:32:21 JST");
A better solution using flexible default values (today instead of 1970-01-01) would be in Java-8 with the new built-in date-time-library located in package java.time:
String input = "12:32:21 JST";
String pattern = "HH:mm:ss z";
LocalDate today = LocalDate.now(ZoneId.of("Asia/Tokyo"));
DateTimeFormatter dtf =
new DateTimeFormatterBuilder().parseDefaulting(ChronoField.YEAR, today.getYear())
.parseDefaulting(ChronoField.MONTH_OF_YEAR, today.getMonthValue()).parseDefaulting(
ChronoField.DAY_OF_MONTH,
today.getDayOfMonth()
).appendPattern(pattern).toFormatter(Locale.ENGLISH);
ZonedDateTime zdt = ZonedDateTime.parse(input, dtf);
System.out.println(zdt); // 2016-12-23T12:32:21+09:00[Asia/Tokyo]
However, I still see a small bug related to the fact that this code makes a hardwired assumption about the used zone BEFORE parsing the real zone so please handle with care. Keep in mind that the current date depends on the zone. But maybe you only need to handle a scenario where just the Japan time is used by users.
Hint: You can also parse in two steps. First step with any kind of fixed default date in order to get the zone information of the text to be parsed. And then you can use this zone information for suggested solution above. An awkward but safe procedure.
You can use this code if you want to change only the year and the day
final SimpleDateFormat simpleDateFormatHour = new SimpleDateFormat("HH:mm:ss z");
Date date = simpleDateFormatHour.parse("12:32:21 JST");
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.YEAR, Calendar.getInstance().get(Calendar.YEAR));
calendar.set(Calendar.DAY_OF_YEAR, Calendar.getInstance().get(Calendar.DAY_OF_YEAR));
date = calendar.getTime();

Date formating issue having + sign

I have date 2016-03-30T23:59:59.000000+0000. May I know what format it is in.
because if I use yyyy-MM-dd'T'HH:mm:ss.SSS, it is throwing an exception
SimpleDateFormat gives you the answer:
yyyy-MM-dd'T'HH:mm:ss.SSSSSSZ
If you really have microseconds different from zero then I strongly advise not to use SimpleDateFormat but Java-8-Time-API or another time library which can handle microseconds. And this is not the only case where the old API proves to be very limited.
Negative example for SimpleDateFormat (broken, milliseconds disappear!!!):
String input = "2016-03-30T23:59:59.123456+0530";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSSZ");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(sdf.format(sdf.parse(input))); // 2016-03-30T18:32:02.000456+0000
Java-8-example (works):
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSZ");
OffsetDateTime odt = OffsetDateTime.parse(input, dtf);
System.out.println(odt); // 2016-03-30T23:59:59.123456+05:30
If you never have microseconds but only milliseconds and want to insist on using the old API then you might try following hack:
String input = "2016-03-30T23:59:59.123000+0530";
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'xxx'Z");
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
sdf2.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(sdf2.format(sdf1.parse(input.replace("000", "xxx"))));
2016-03-30T18:29:59.123+0000
However, this "solution" breaks for year 2000 (you can find a better one by further string preprocessing), and eventually available microseconds get lost. So using SimpleDateFormat is a bad idea here.

Java 8 Timezone conversion when creating java.util.Date [duplicate]

This question already has answers here:
Java program to get the current date without timestamp
(17 answers)
Closed 6 years ago.
I want to create a Date object without a TimeZone (eg : 2007-06-21). Is this possible?
When I use the following method it prints like Thu Jun 21 00:00:00 GMT 2007
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
TimeZone timeZone = TimeZone.getTimeZone("GMT");
timeZone.setDefault(timeZone);
sdf.setTimeZone(timeZone);
Date pickUpDate = sdf.parse("2007-06-21");
System.out.println(pickUpDate);
If you want to format a date, you need to use DateFormat or something similar. A Date is just an instant in time - the number of milliseconds since the Unix epoch. It doesn't have any idea of time zone, calendar system or format. The toString() method always uses the system local time zone, and always formats it in a default way. From the documentation:
Converts this Date object to a String of the form:
dow mon dd hh:mm:ss zzz yyyy
So it's behaving exactly as documented.
You've already got a DateFormat with the right format, so you just need to call format on it:
System.out.println("pickUpDate" + sdf.format(pickUpDate));
Of course it doesn't make much sense in your sample, given that you've only just parsed it - but presumably you'd normally be passing the date around first.
Note that if this is for interaction with a database, it would be better not to pass it as a string at all. Keep the value in a "native" representation for as much of the time as possible, and use something like PreparedStatement.setDate to pass it to the database.
As an aside, if you can possibly change to use Joda Time or the new date/time API in Java 8 (java.time.*) you'll have a much smoother time of it with anything date/time-related. The Date/Calendar API is truly dreadful.
This is the toString() of the java.util.Date
public String toString() {
// "EEE MMM dd HH:mm:ss zzz yyyy";
BaseCalendar.Date date = normalize();
StringBuilder sb = new StringBuilder(28);
int index = date.getDayOfWeek();
if (index == gcal.SUNDAY) {
index = 8;
}
convertToAbbr(sb, wtb[index]).append(' '); // EEE
convertToAbbr(sb, wtb[date.getMonth() - 1 + 2 + 7]).append(' '); // MMM
CalendarUtils.sprintf0d(sb, date.getDayOfMonth(), 2).append(' '); // dd
CalendarUtils.sprintf0d(sb, date.getHours(), 2).append(':'); // HH
CalendarUtils.sprintf0d(sb, date.getMinutes(), 2).append(':'); // mm
CalendarUtils.sprintf0d(sb, date.getSeconds(), 2).append(' '); // ss
TimeZone zi = date.getZone();
if (zi != null) {
sb.append(zi.getDisplayName(date.isDaylightTime(), zi.SHORT, Locale.US)); // zzz
} else {
sb.append("GMT");
}
sb.append(' ').append(date.getYear()); // yyyy
return sb.toString();
}
So, if you will pass a Date and try to print it this will be printed out all the time.
Code:
Date date = new Date();
System.out.println(new SimpleDateFormat("yyyy-MM-dd").format(date));
Date : Fri Apr 29 04:53:16 GMT 2016
Sample Output : 2016-04-29
Imports required :
import java.util.Date; //for new Date()
import java.text.SimpleDateFormat; // for the format change
System.out.println("pickUpDate " + sdf.format(pickUpDate));
You can use the above code to get formatted Date as String
Use this Code:
SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd");
Date pickUpDate =sdf.parse("2007-06-21");
System.out.println("pickUpDate "+sdf.format(pickUpDate));
Hope it'll help you.
String your_format_date=sdf.format(pickUpDate);
System.out.println("pick Up Date " + your_format_date);
Date isn't a date. It's a timestamp. That's some impressive API design, isn't it?
The type you need is now java.time.LocalDate, added in Java 8.
If you can't use Java 8, you can use ThreeTen, a backport for Java 7.

How to remove milliseconds from LocalTime in java 8

Using the java.time framework, I want to print time in format hh:mm:ss, but LocalTime.now() gives the time in the format hh:mm:ss,nnn. I tried to use DateTimeFormatter:
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_TIME;
LocalTime time = LocalTime.now();
String f = formatter.format(time);
System.out.println(f);
The result:
22:53:51.894
How can I remove milliseconds from the time?
Edit: I should add that these are nanoseconds not milliseconds.
I feel these answers don't really answer the question using the Java 8 SE Date and Time API as intended. I believe the truncatedTo method is the solution here.
LocalDateTime now = LocalDateTime.now();
System.out.println("Pre-Truncate: " + now);
DateTimeFormatter dtf = DateTimeFormatter.ISO_DATE_TIME;
System.out.println("Post-Truncate: " + now.truncatedTo(ChronoUnit.SECONDS).format(dtf));
Output:
Pre-Truncate: 2015-10-07T16:40:58.349
Post-Truncate: 2015-10-07T16:40:58
Alternatively, if using Time Zones:
LocalDateTime now = LocalDateTime.now();
ZonedDateTime zoned = now.atZone(ZoneId.of("America/Denver"));
System.out.println("Pre-Truncate: " + zoned);
DateTimeFormatter dtf = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
System.out.println("Post-Truncate: " + zoned.truncatedTo(ChronoUnit.SECONDS).format(dtf));
Output:
Pre-Truncate: 2015-10-07T16:38:53.900-06:00[America/Denver]
Post-Truncate: 2015-10-07T16:38:53-06:00
cut to minutes:
localTime.truncatedTo(ChronoUnit.MINUTES);
cut to seconds:
localTime.truncatedTo(ChronoUnit.SECONDS);
Example:
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
LocalTime.now()
.truncatedTo(ChronoUnit.SECONDS)
.format(DateTimeFormatter.ISO_LOCAL_TIME);
Outputs 15:07:25
Just create the DateTimeFormatter explicitly:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss", Locale.US);
LocalTime time = LocalTime.now();
String f = formatter.format(time);
System.out.println(f);
(I prefer to explicitly use the US locale, to make it clear that I don't want anything from the default format locale.)
Use this in your first line
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss");
Try to use patterns defined here: http://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html
For example:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy MM dd HH. mm. ss");
String text = date.toString(formatter);
You can so it simply by using regex on the string:
String f = formatter.format(time).replaceAll("\\.[^.]*", "");
This deletes (by replacing with blank) the last dot and everything after.

How do I create the java date object without time stamp [duplicate]

This question already has answers here:
Java program to get the current date without timestamp
(17 answers)
Closed 6 years ago.
I want to create a Date object without a TimeZone (eg : 2007-06-21). Is this possible?
When I use the following method it prints like Thu Jun 21 00:00:00 GMT 2007
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
TimeZone timeZone = TimeZone.getTimeZone("GMT");
timeZone.setDefault(timeZone);
sdf.setTimeZone(timeZone);
Date pickUpDate = sdf.parse("2007-06-21");
System.out.println(pickUpDate);
If you want to format a date, you need to use DateFormat or something similar. A Date is just an instant in time - the number of milliseconds since the Unix epoch. It doesn't have any idea of time zone, calendar system or format. The toString() method always uses the system local time zone, and always formats it in a default way. From the documentation:
Converts this Date object to a String of the form:
dow mon dd hh:mm:ss zzz yyyy
So it's behaving exactly as documented.
You've already got a DateFormat with the right format, so you just need to call format on it:
System.out.println("pickUpDate" + sdf.format(pickUpDate));
Of course it doesn't make much sense in your sample, given that you've only just parsed it - but presumably you'd normally be passing the date around first.
Note that if this is for interaction with a database, it would be better not to pass it as a string at all. Keep the value in a "native" representation for as much of the time as possible, and use something like PreparedStatement.setDate to pass it to the database.
As an aside, if you can possibly change to use Joda Time or the new date/time API in Java 8 (java.time.*) you'll have a much smoother time of it with anything date/time-related. The Date/Calendar API is truly dreadful.
This is the toString() of the java.util.Date
public String toString() {
// "EEE MMM dd HH:mm:ss zzz yyyy";
BaseCalendar.Date date = normalize();
StringBuilder sb = new StringBuilder(28);
int index = date.getDayOfWeek();
if (index == gcal.SUNDAY) {
index = 8;
}
convertToAbbr(sb, wtb[index]).append(' '); // EEE
convertToAbbr(sb, wtb[date.getMonth() - 1 + 2 + 7]).append(' '); // MMM
CalendarUtils.sprintf0d(sb, date.getDayOfMonth(), 2).append(' '); // dd
CalendarUtils.sprintf0d(sb, date.getHours(), 2).append(':'); // HH
CalendarUtils.sprintf0d(sb, date.getMinutes(), 2).append(':'); // mm
CalendarUtils.sprintf0d(sb, date.getSeconds(), 2).append(' '); // ss
TimeZone zi = date.getZone();
if (zi != null) {
sb.append(zi.getDisplayName(date.isDaylightTime(), zi.SHORT, Locale.US)); // zzz
} else {
sb.append("GMT");
}
sb.append(' ').append(date.getYear()); // yyyy
return sb.toString();
}
So, if you will pass a Date and try to print it this will be printed out all the time.
Code:
Date date = new Date();
System.out.println(new SimpleDateFormat("yyyy-MM-dd").format(date));
Date : Fri Apr 29 04:53:16 GMT 2016
Sample Output : 2016-04-29
Imports required :
import java.util.Date; //for new Date()
import java.text.SimpleDateFormat; // for the format change
System.out.println("pickUpDate " + sdf.format(pickUpDate));
You can use the above code to get formatted Date as String
Use this Code:
SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd");
Date pickUpDate =sdf.parse("2007-06-21");
System.out.println("pickUpDate "+sdf.format(pickUpDate));
Hope it'll help you.
String your_format_date=sdf.format(pickUpDate);
System.out.println("pick Up Date " + your_format_date);
Date isn't a date. It's a timestamp. That's some impressive API design, isn't it?
The type you need is now java.time.LocalDate, added in Java 8.
If you can't use Java 8, you can use ThreeTen, a backport for Java 7.

Categories

Resources