Date as longvalue to LocalDateTime - java

How to convert a long value like 2018051822111234L to yyyyMMdd HH:mm?
2018051822111234 -> 2018 05 18 22:11:12.
I tried with LocalDate.parse and DateFormatter(yyyy-MM-dd'T'HH:mm:ssZZZZZ). It doesn’t work for me.

String asString = Long.toString(2018051822111234L);
asString = asString.substring(0, asString.length() - 2);
String result = LocalDateTime.parse(asString, DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))
.format(DateTimeFormatter.ofPattern("yyyy MM dd HH:mm:ss"));

Monsieur Nizet has already provided an excellent answer. It’s just me: I’d like to parse the full precision of the input long. It’s easier to throw away information later than it is to add it later if it wasn’t parsed at first.
Java 9 solution:
DateTimeFormatter longFormatter = DateTimeFormatter.ofPattern("uuuuMMddHHmmssSS");
DateTimeFormatter desiredFormatter = DateTimeFormatter.ofPattern("uuuu MM dd HH:mm:ss");
String asString = Long.toString(2018051822111234L);
String result = LocalDateTime.parse(asString, longFormatter)
.format(desiredFormatter);
This prints
2018 05 18 22:11:12
As you have already said yourself, this doesn’t work in Java 8 because of this bug in the JRE: DateTimeFormatter won't parse dates with custom format "yyyyMMddHHmmssSSS". The bug report mentions the following workaround:
DateTimeFormatter longFormatter = new DateTimeFormatterBuilder()
.appendPattern("uuuuMMddHHmmss")
.appendValue(ChronoField.MILLI_OF_SECOND, 3)
.toFormatter();
asString += '0';
The workaround formatter has three decimals on the seconds, corresponding to milliseconds, whereas your long has only two. So above I am appending an extra 0 to the string before parsing. It was what I could get to work in Java 8 (also tried appendFraction(), in vain). Now the result is the same as above.

Related

Generic date parsing in java

I have date strings in various formats like Oct 10 11:05:03 or 12/12/2016 4:30 etc
If I do
// some code...
getDate("Oct 10 11:05:03", "MMM d HH:mm:ss");
// some code ...
The date gets parsed, but I am getting the year as 1970 (since the year is not specified in the string.) But I want the year as current year if year is not specidied. Same applies for all fields.
here is my getDate function:
public Date getDate(dateStr, pattern) {
SimpleDateFormat parser = new SimpleDateFormat(pattern);
Date date = parser.parse(myDate);
return date;
}
can anybody tell me how to do that inside getDate function (because I want a generic solution)?
Thanks in advance!
If you do not know the format in advance, you should list the actual formats you are expecting and then try to parse them. If one fails, try the next one.
Here is an example of how to fill in the default.
You'll end up with something like this:
DateTimeFormatter f = new DateTimeFormatterBuilder()
.appendPattern("ddMM")
.parseDefaulting(YEAR, currentYear)
.toFormatter();
LocalDate date = LocalDate.parse("yourstring", f);
Or even better, the abovementioned formatter class supports optional elements. Wrap the year specifier in square brackets and the element will be optional. You can then supply a default with parseDefaulting.
Here is an example:
String s1 = "Oct 5 11:05:03";
String s2 = "Oct 5 1996 13:51:56"; // Year supplied
String format = "MMM d [uuuu ]HH:mm:ss";
DateTimeFormatter f = new DateTimeFormatterBuilder()
.appendPattern(format)
.parseDefaulting(ChronoField.YEAR, Year.now().getValue())
.toFormatter(Locale.US);
System.out.println(LocalDate.parse(s1, f));
System.out.println(LocalDate.parse(s2, f));
Note: Dates and times are not easy. You should take into consideration that date interpreting is often locale-dependant and this sometimes leads to ambiguity. For example, the date string "05/12/2018" means the 12th of May, 2018 when you are American, but in some European areas it means the 5th of December 2018. You need to be aware of that.
One option would be to concatenate the current year onto the incoming date string, and then parse:
String ts = "Oct 10 11:05:03";
int currYear = Calendar.getInstance().get(Calendar.YEAR);
ts = String.valueOf(currYear) + " " + ts;
Date date = getDate(ts, "yyyy MMM d HH:mm:ss");
System.out.println(date);
Wed Oct 10 11:05:03 CEST 2018
Demo
Note that we could have used StringBuilder above, but the purpose of brevity of code, I used raw string concatenations instead. I also fixed a few typos in your helper method getDate().

Wildcard in DateTimeFormatter

I need to parse a string into a LocalDate. The string looks like 31.* 03 2016 in regex terms (i.e. .* means that there may be 0 or more unknown characters after the day number).
Example input/output: 31xy 03 2016 ==> 2016-03-31
I was hoping to find a wildcard syntax in the DateTimeFormatter documentation to allow a pattern such as:
LocalDate.parse("31xy 03 2016", DateTimeFormatter.ofPattern("dd[.*] MM yyyy"));
but I could not find anything.
Is there a simple way to express optional unknown characters with a DateTimeFormatter?
ps: I can obviously modify the string before parsing it but that's not what I'm asking for.
There is no direct support for this in java.time.
The closest would be to use parse(CharSequence,ParsePosition) using two different formatters.
// create the formatter for the first half
DateTimeFormatter a = DateTimeFormatter.ofPattern("dd")
// setup a ParsePosition to keep track of where we are in the parse
ParsePosition pp = new ParsePosition();
// parse the date, which will update the index in the ParsePosition
String str = "31xy 03 2016";
int dom = a.parse(str, pp).get(DAY_OF_MONTH);
// some logic to skip the messy 'xy' part
// logic must update the ParsePosition to the start of the month section
pp.setIndex(???)
// use the parsed day-of-month in the formatter for the month and year
DateTimeFormatter b = DateTimeFormatter.ofPattern("MM yyyy")
.parseDefaulting(DAY_OF_MONTH, dom);
// parse the date, using the *same* ParsePosition
LocalDate date = b.parse(str, pp).query(LocalDate::from);
While the above is untested it should basically work. However, it would be far easier parse it manually.
I’d do it in two steps, use a regexp to get the original string into something that LocalDate can parse, for example:
String dateSource = "31xy 03 2016";
String normalizedDate = dateSource.replaceFirst("^(\\d+).*? (\\d+ \\d+)", "$1 $2");
LocalDate date = LocalDate.parse(normalizedDate, DateTimeFormatter.ofPattern("dd MM yyyy"));
System.out.println(date);
I know it’s not what you asked for.

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.

Java LocalDateTime parse error [duplicate]

This question already has answers here:
How to parse case-insensitive strings with JSR-310 DateTimeFormatter?
(3 answers)
Closed 6 years ago.
Been trying for 4 hours to figure this out.
:This works
String date = "Jul-01-2014 09:10:12";
LocalDateTime dt = LocalDateTime.parse(date, DateTimeFormatter.ofPattern("MMM-dd-yyyy HH:mm:ss", Locale.US));
:This will not
String date = "JUL-01-2014 09:10:12";
LocalDateTime dt = LocalDateTime.parse(date, DateTimeFormatter.ofPattern("MMM-dd-yyyy HH:mm:ss", Locale.US));
Only difference being the month all capitalized. Proper case of Jul works. Neither JUL or jul will work. I also tried pattern of 'LLL' with no luck. What am I missing??
Well apparently I needed to spend 5 hours on this.
While writing an extension to provide a workaround I discovered this.
String date = "01-JUL-2014 09:10:12";
DateTimeFormatterBuilder fmb = new DateTimeFormatterBuilder();
fmb.parseCaseInsensitive();
fmb.append(DateTimeFormatter.ofPattern("dd-MMM-yyyy HH:mm:ss"));
LocalDateTime dt = LocalDateTime.parse(date, fmb.toFormatter());
Works great for all case styles.
It doesn't look like that is supported by the official API.
Symbol Meaning Presentation Examples
------ ------- ------------ -------
G era text AD; Anno Domini; A
u year year 2004; 04
y year-of-era year 2004; 04
D day-of-year number 189
M/L month-of-year number/text 7; 07; Jul; July; J
d day-of-month number 10
The only option for month-of-year is there, and it does not explicitly mention any format supporting three capital letter months.
It's not terribly difficult to convert it back into a format that Java can respect though; it involves a wee bit of finagling the date and putting it back into a single String, though.
The solution below isn't as elegant or as clean as using a third party, but the added benefit is that one doesn't have to rely on the third party library for this code at all.
public String transformToNormalizedDateFormat(final String input) {
String[] components = input.split("-");
String month = components[0];
if(month.length() > 3) {
throw new IllegalArgumentException("Was not a date in \"MMM\" format: " + month);
}
// Only capitalize the first letter.
final StringBuilder builder = new StringBuilder();
builder.append(month.substring(0, 1).toUpperCase())
.append(month.substring(1).toLowerCase())
.append("-");
final StringJoiner stringJoiner = new StringJoiner("-");
Arrays.stream(components, 1, components.length).forEach(stringJoiner::add);
builder.append(stringJoiner.toString());
return builder.toString();
}
Try using DateTimeFormatterBuilder and making parser case-insensitive. Don't forget to specify locale. Otherwise month abbreviation might not be parsed by MMM in default locale:
DateTimeFormatter format = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern("dd-MMM-yyyy")
.toFormatter(Locale.ENGLISH);
LocalDate.parse("03-jun-2015", format);
M by definition takes July; Jul; 07. You might want to try (solution being a little ugly):
date = Character.toUpperCase(date.charAt(0)) + date.substring(1).toLowerCase();
LocalDateTime dt = LocalDateTime.parse(date, DateTimeFormatter.ofPattern("MMM-dd-yyyy HH:mm:ss", Locale.US));
Or you can try using WordUtils from apache-commons for capitalize.

DateFormat Pattern for some strings

I have some different format of date to parse but I cannot recognize them with SimpleDateFormat. Can anybody help me to find patterns for this dates:
6 July 1892
9 May 1915
February 335
1768-02-12
and
23 september 63 bc
19 august ad 14
Thanks
You just provide possibilities of patterns you want your dates to be parsed by and run through them finding the first matching.
Run solution.
Joda is generally better if you have to parse using multiple formats. For example,
private static DateTimeFormatter dateFormatter;
String[] validDateFormats = new String[] { "dd-MMM-yyyy HH:mm:ss",
"yyyy-MM-dd HH:mm:ss.SSS" };
DateTimeParser[] parsers = new DateTimeParser[validDateFormats.length];
for (int i = 0; i < validDateFormats.length; ++i) {
parsers[i] = DateTimeFormat.forPattern(validDateFormats[i])
.getParser();
}
dateFormatter = new DateTimeFormatterBuilder().append(null, parsers)
.toFormatter().withZone(DateTimeZone.UTC);
Now this dateFormatter will parse correctly if the input matches any of the formats:
inputDate = dateFormatter.parseDateTime(dateStr);
DateTimeFormatter outputFormat = DateTimeFormat
.forPattern("yyyy/MM/dd");
String outputString = inputDate.toString(outputFormat);
The format strings can be looked up from here: http://joda-time.sourceforge.net/api-release/org/joda/time/format/DateTimeFormat.html
Here you can find a great generator for creating every date format you can imagine
http://www.fileformat.info/tip/java/simpledateformat.htm
E.g. your first both examples are generated with dd MMMM yyyy ;)
Try these
27-May-2012:
System.out.println(new SimpleDateFormat("d-MMM-YYYY").format(new Date()));
27-05-2012 :
System.out.println(new SimpleDateFormat("d-MM-YYYY").format(new Date()));
27-05-12 :
System.out.println(new SimpleDateFormat("dd-MM-YY").format(new Date()));

Categories

Resources