I am currently struggling to refactor this piece of old code to use the new java.time.format.DateTimeFormatter because it is used in our main logging component where this creates unnecessary garbage.
private String getFormattedDate(final Date date) {
// a new instance is created foreach log message
SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
return dateFormat.format(date);
}
I already tried the new ISO_INSTANT formater like:
DateTimeFormatter.ISO_INSTANT.format(date.toInstant());
but this gives (slightly) different output as before.
My test shows:
Expected: is "2013-10-22T05:23:48.397+0200"
but: was "2013-10-22T03:23:48.397Z"
So I need the time zone offset to be included in the format string as shown in Expected.
I know about the DateTimeFormatterBuilder but I didnt manage to build it in a way to get my desired format output.
How would I need to do this?
I know I can always fall back to using a single thread local SimpleDateFormat instance but I would like to use the new java.time stuff :-)
Date date = new Date();
System.out.println(DateTimeFormatter.ISO_INSTANT.format(date.toInstant()));
// output: 2015-11-22T14:46:08.776Z
System.out.println(DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(
date.toInstant().atZone(ZoneId.systemDefault())));
// output: 2015-11-22T15:46:08.776+01:00
System.out.println(DateTimeFormatter.ISO_OFFSET_DATE_TIME
.withZone(ZoneId.systemDefault())
.format(date.toInstant()));
// output: 2015-11-22T15:46:08.776+01:00
Related
Firstly, I'm a C# dev learning Java. I'm converting a program I wrote in C# as an exercise and am having problems with parsing a date being submitted from an html form. The form is sent as an email and the java program reads the emails and parses the body. I have a drop down calendar for my peeps to select a date from but there's always some jerk who has to type it in and mess everything up. Currently I am doing this in my code:
public void SetDatePlayed(String datePlayed)
{
this.datePlayed = LocalDate.parse(datePlayed);
}
datePlayed being passed in is a string usually formatted as yyyy-MM-dd but of course someone typed in 3/7 instead of using the calendar drop down on the form. this.datePlayed is a LocalDate. In C# I would just end up with a date that assumed 2020 for the year - no problem. LocalDate really wants it in the yyyy-MM-dd format and I don't know what the best practice here is with Java. I've been googling it all morning and haven't come across this as being an issue for anyone else. I don't care if I'm using LocalDate but I do need it to be a date datatype so I can do date checks, sorts, searches, etc later on.
You can use DateTimeFormatterBuilder and parseDefaulting() to supply default value for the year.
Building on the answer by Sweeper, it can be done like this:
static LocalDate parseLoosely(String text) {
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
.appendPattern("[uuuu-M-d][M/d/uuuu][M/d]")
.parseDefaulting(ChronoField.YEAR, Year.now().getValue())
.toFormatter();
return LocalDate.parse(text, fmt);
}
Warning: Do not cache the formatter in e.g. a static field, since it snapshots the year, if the program might be running across New Year's Eve, which a webapp would, unless you add logic to make the cache auto-refresh on year change.
Test
System.out.println(parseLoosely("2019-04-07"));
System.out.println(parseLoosely("2019-4-7"));
System.out.println(parseLoosely("4/7/2019"));
System.out.println(parseLoosely("4/7"));
Output
2019-04-07
2019-04-07
2019-04-07
2020-04-07
I see two possible interpretations of your question. I'm not sure which one it is, so I'll answer both.
How do I parse a date string in a format that has no year, such as M/d (3/7), to a LocalDate?
You don't. A LocalDate by definition must have year, month, and day. If you only have a month and a day, that's a MonthDay:
MonthDay md = MonthDay.parse("3/7", DateTimeFormatter.ofPattern("M/d"));
If you want the current year added to it, you can do it later:
LocalDate ld = md.atYear(Year.now(/*optionally insert time zone*/).getValue());
How do I handle both yyyy-MM-dd and M/d patterns?
Here's one way: create a DateTimeFormatter that recognises both patterns, parse the string to a TemporalAccessor, check if the TemporalAccessor supports the "year" field:
TemporalAccessor ta = DateTimeFormatter.ofPattern("[M/d][yyyy-MM-dd]").parse("3/7");
if (ta.isSupported(ChronoField.YEAR_OF_ERA)) { // yyyy-MM-dd
LocalDate ld = LocalDate.from(ta);
} else if (ta.isSupported(ChronoField.MONTH_OF_YEAR)) { // M/d
MonthDay md = MonthDay.from(ta);
} else {
// user has entered an empty string, handle error...
}
I am trying to retrieve the current date in the following format: 21-FEB-17.
I have the following code but it isn't the format I need. It prints out in the following format: 21-February-17.
Format formatter = new SimpleDateFormat("dd-MMMM-yy");
String today = formatter.format(new Date());
System.out.println(today);
To get the "first 3 letters" of the month, you should use
Format formatter = new SimpleDateFormat("dd-MMM-yy");
as per the Oracle documentation of SimpleDateFormat.
That will print the month in "Camel" case (i.e., "Feb"). If you want it in all uppercase, you need to do
System.out.println(today.toUpperCase());
Your format had and extra M:
Format formatter = new SimpleDateFormat("dd-MMM-yy");
String today = formatter.format(new Date());
System.out.println(today.toUpperCase());
Here is the link to help you understand better.
And to answer your question use below code.
Format formatter = new SimpleDateFormat("dd-MMM-yy");
String today = formatter.format(new Date());
System.out.println(today.toUpperCase());
This is not the answer you asked for, but it may be the answer you want. :-) As Bojan Petkovic has already said in a comment, if there’s any way you can use Java 8, you will want to use the new java.time classes:
final Locale myLocale = Locale.US;
String today = LocalDate.now()
.format(DateTimeFormatter.ofPattern("d-MMM-yy", myLocale))
.toUpperCase(myLocale);
System.out.println(today);
This prints:
22-FEB-17
You will notice I explicitly use a locale object both for the formatter and for converting to uppercase. You know best which locale you want to use. You may also leave out the locale argument in both places, then the computer’s default locale will be used (so you will get different results on different computers). For a locale neutral formatting, use Locale.ROOT (it will be rather like Locale.US).
I have an app that was using SimpleDateFormat that we have since multithreaded and SimpleDateFormat is causing some issues.
I have read a bit about FastDateFormat but have never used it and would like to know how to do the following.
Currently I do something along the lines of :
String myDateString = "2015-08-10";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date myDate = sdf.parse(myDateString);
What is the equivalent to that using FastDateFormat?
I got as far as
FastDateFormat fdf = FastDateFormat.getInstance("yyyy-MM-dd");
But after that I dont see a clearcut way to get a Date instance returned.
Okay, so here's my issue in Android right now. On our Database there's a timestamp in this format 8/15/2013 2:00:48 PM and through a .NET WebService I get that same time like this in Android: 2013-08-15T14:00:48-07:00. Now I want to convert this format into a Date Time format that I can use for comparison (for example this webservice provides every instance where a device failed at logging in so we want to check the amount of time between occurances to see if there's any issues). Below I have this code where I'm trying to use JODA Time but it's still not returning the correct format:
public static Date convertStringToDate(String input) {
String pattern = "yyyy-MM-dd'T'HH:mm:ssZ";
DateTimeFormatter formatter = DateTimeFormat.forPattern(pattern);
DateTime dateTime = formatter.parseDateTime(input);
return dateTime.toDate();
//printout shows: Thu Aug 15 17:00:48 EDT 2013
}
I know that the server is returning some crappy time format that is hard to work with (it took a while to get this to work in the iOS App we have, and even there it's still rather clunky) so I don't mind changing the webservice or the query if that would make things easier.
I have a very similar format, and I parse it using SimpleDateFormat, try this:
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZZZ", Locale.US);
Date dateTime = format .parse(value);
What i understand is that you have your correct instance of date already and what you need is to parse it to String.
I suggest you use:
DateFormat formatter = new SimpleDateFormat("d/MM/yyyy hh:mm:ss a");
//this will give you the format '8/15/2013 2:00:48 PM'
String d = formatter.format(date);
Hope this helps.
EDIT:
Also seams you want to have your date instance in -07:00 timezone
So you can change your line
DateTime dateTime = formatter.parseDateTime(input);
for
DateTime dateTime = formatter.withZone(DateTimeZone.forID("-07:00")).parseDateTime(input);
The following Java test passes on our US hosted build server. It also passes on non-US servers, e.g. in Germany. It fails on my local server, which is running in Ireland. The following code illustrates a failing test.
org.junit.ComparisonFailure: expected:<[4/6/09 11:30 AM]> but was:<[06/04/09 11:30]>
Is there a system setting I can provide to get these tests passing locally?
public void testFormattedDate() {
// Set the default time zone in case this unit test is executed in a different country
TimeZone.setDefault(TimeZone.getTimeZone(DateUtil.DEFAULT_TIMEZONE));
final Date utilDate = new Date();
utilDate.setDate(6);
utilDate.setHours(11);
utilDate.setMinutes(30);
utilDate.setMonth(3);
utilDate.setSeconds(45);
utilDate.setYear(109);
SimpleDateFormat dateFormatter = new SimpleDateFormat();
final String formattedOutput = dateFormatter.format(utilDate);
Assert.assertEquals("4/6/09 11:30 AM", formattedOutput);
}
Have to tried to provide a pattern to the SimpleDateFormat ?
SimpleDateFormat dateFormatter = new SimpleDateFormat("d/M/yy HH:mm a");
The time is correct but the SimpleDateFormat() constructor internally calls a package private construtor using Locale.getDefault(). Thus you either can provide a format of your own or provide another locale, which seems to only be possible with a custom format, i.e. using SimpleDateFormat(String pattern, Locale locale).
The problem is that SimpleDateFormat() uses a locale dependent pattern, thus the system's default locale might result in a different pattern than what you get in the USA (I assume the German server doesn't use the German locale as its default since then you should get a date like 06.04.09 11:30).