I've got the following date as a string
2017-03-01T10:15:41-0800
that I'm trying to use with
new Date().parse('dd/mm/yyyy', dateString)
However, I can't figure out the format.
Your dateString and date format dont match.
Groovy Style:
def dateString = "2017-03-01T10:15:41-0800"
new Date().parse("yyyy-MM-dd'T'HH:mm:ssZ", dateString)
Result:
Wed Mar 01 21:15:41 EAT 2017
You can refer here for more information about the date format pattern.
Consider using SimpleDateFormat:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
class Main {
public static void main(String[] args) {
try {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ssX");
Date parsed = format.parse("2017-03-01T10:15:41-0800");
} catch (ParseException e){
e.printStackTrace();
}
}
}
Try it here!
Date class contains its own, static parse method (JB Nizet was wrong in his comment to your question).
For details see http://docs.groovy-lang.org/latest/html/groovy-jdk/java/util/Date.html#parse(java.lang.String,%20java.lang.String)
So if you perform this parsing only once, use just this method.
On the other hand, if you plan to perform such a conversion multiple times,
it is more efficient to create a SimpleDateFormat instance (once)
and then use it multiple times.
If you can, and you're on Java 8, avoid java.util.Date, and parse it into one of the new java.time classes:
import java.time.*
import java.time.format.DateTimeFormatter
def dateString = "2017-03-01T10:15:41-0800"
def date = OffsetDateTime.parse(dateString,
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ"))
If you then want this time in another zone (ie: UTC), you can do:
def utcDate = date.atZoneSameInstant(ZoneOffset.UTC)
Related
Java.util.date package is auto correcting date. For ex: if we pass date as "2018-02-35", it automatically changes it to "2018-03-07", which is a valid date.
Basically, the requirement is to validate the user entered date but as the date is getting auto corrected the module was never able to find an incorrect date. (Note: UI validation can't be done due to some special restrictions so the validation has to be done by the middleware system).
Is there a way i can handle this with the same util package or can this be handled through any 3rd party jar? pls advise
Even i faced same issue. But after some research i found that there is method (setLenient()) in the DateFormat class to disable this behaviour.
DateFormat df = new SimpleDateFormat(DATE_FORMAT);
df.setLenient(false);
Java Docs:
Specify whether or not date/time parsing is to be lenient. With lenient parsing, the parser may use heuristics to interpret inputs that do not precisely match this object's format. With strict parsing, inputs must match this object's format.
you can write DateDeserializer
public class DateDeserializer extends JsonDeserializer<Date> {
#Override
public Date deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd", getLocale());
format.setLenient(false); // if true, will auto correct the date
// to the next possible valid date
String date = jp.getText();
try {
return format.parse(date);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
private Locale getLocale() {
Locale locale = (LocaleContextHolder.getLocale() != null) ? LocaleContextHolder.getLocale() : Locale.getDefault();
return locale;
}
}
And then annotate your date property in the media class with this DateDeserializer. You can also use dateSerializer to serialize the object back to Json format. Example below
#JsonSerialize(using=DateSerializer.class)
#JsonDeserialize(using=DateDeserializer.class)
private Date startDate;
Today I'm parsing epoch time to a String, like this:
private String convertEpochTime(Long timeInEpoch) {
return new SimpleDateFormat("MM/dd/yyyy HH:mm")
.format(new java.util.Date (timeInEpoch * 1000));
}
I want to use Java 8 new LocalDate API, instead of using a String, but didn't find a way of doing it.
I wish I just could do:
private LocalDate convertEpochTime(Long timeInEpoch) {
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("MM/dd/yyyy HH:mm").format(new java.util.Date (timeInEpoch * 1000));
return LocalDate.parse(dateTimeFormatter);
}
Is there any way of doing it?
You can use Instant.ofEpochSecond and then convert the instant to a LocalDate:
Instant instant = Instant.ofEpochSecond(timeInEpoch);
LocalDate localDate = instant.atZone(ZoneId.systemDefault()).toLocalDate();
or if you want to have time as well, convert to a LocalDateTime:
LocalDateTime localDateTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();
Instead of ZoneId.systemDefault() you may need to use a different zone depending on your needs.
So there is no need to use a string as intermediary.
How can I best convert a java.util.Date to a Java 8 java.time.YearMonth?
Unfortunately the following throws a DateTimeException:
YearMonth yearMonth = YearMonth.from(date.toInstant());
results in:
java.time.DateTimeException: Unable to obtain YearMonth from TemporalAccessor: 2015-01-08T14:28:39.183Z of type java.time.Instant
at java.time.YearMonth.from(YearMonth.java:264)
...
I need this functionality since I want to store YearMonth values in a database using JPA. Currently JPA does not support YearMonth's, so I've come up with the following YearMonthConverter (imports omitted):
// TODO (future): delete when next version of JPA (i.e. Java 9?) supports YearMonth. See https://java.net/jira/browse/JPA_SPEC-63
#Converter(autoApply = true)
public class YearMonthConverter implements AttributeConverter<YearMonth, Date> {
#Override
public Date convertToDatabaseColumn(YearMonth attribute) {
// uses default zone since in the end only dates are needed
return attribute == null ? null : Date.from(attribute.atDay(1).atStartOfDay(ZoneId.systemDefault()).toInstant());
}
#Override
public YearMonth convertToEntityAttribute(Date dbData) {
// TODO: check if Date -> YearMonth can't be done in a better way
if (dbData == null) return null;
Calendar calendar = Calendar.getInstance();
calendar.setTime(dbData);
return YearMonth.of(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1);
}
}
Isn't there a better (cleaner, shorter) solution (for both directions)?
Short answer:
// From Date to YearMonth
YearMonth yearMonth =
YearMonth.from(date.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDate());
// From YearMonth to Date
// The same as the OP:s answer
final Date convertedFromYearMonth =
Date.from(yearMonth.atDay(1).atStartOfDay(ZoneId.systemDefault()).toInstant());
Explanation:
The JavaDoc of the YearMonth.from(TemporalAccessor)-method says:
The conversion extracts the YEAR and MONTH_OF_YEAR fields. The extraction is only permitted if the temporal object has an ISO chronology, or can be converted to a LocalDate.
So, you need to either be able to:
extract the YEAR and MONTH_OF_YEAR fields, or
you should use something that can be converted to a LocalDate.
Lets try it!
final Date date = new Date();
final Instant instant = date.toInstant();
instant.get(ChronoField.YEAR); // causes an error
This is not possible, an exception is thrown:
java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: Year
at java.time.Instant.get(Instant.java:571)
...
This means that alternative 1 goes out the window. The reason for is explained in this excellent answer about how to convert Date to LocalDate.
Despite its name, java.util.Date represents an instant on the time-line, not a "date". The actual data stored within the object is a long count of milliseconds since 1970-01-01T00:00Z (midnight at the start of 1970 GMT/UTC).
The equivalent class to java.util.Date in JSR-310 is Instant, thus there is a convenient method toInstant() to provide the conversion.
So, a Date can be converted to an Instant but that did not help us, did it?
Alternative 2 however proves to be successful. Convert the Instant to a LocalDate and then use the YearMonth.from(TemporalAccessor)-method.
Date date = new Date();
LocalDate localDate = date.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDate();
YearMonth yearMonth = YearMonth.from(localDate);
System.out.println("YearMonth: " + yearMonth);
The output is (since the code was executed in January 2015 ;):
YearMonth: 2015-01
I'm trying to format a date in a Scala template in Play. So far I've written this:
<p>#DateFormat.getInstance().format(deadline)</p>
Where deadline is the date I'm outputting to the web page. However, this uses the JVM's locale and not the one selected by the user.
My app currently supports two locales, Norwegian (no) and English (en). This works well for messages, but not for Dates. So I tried adding a GlobalSettings to intercept each request as shown below, but apparently it's never invoked:
import java.lang.reflect.Method;
import java.util.Locale;
import org.springframework.context.i18n.LocaleContext;
import org.springframework.context.i18n.LocaleContextHolder;
import play.GlobalSettings;
import play.i18n.Lang;
import play.mvc.Action;
import play.mvc.Http.Request;
public class Global extends GlobalSettings {
#SuppressWarnings("rawtypes")
#Override
public Action onRequest(final Request request, final Method actionMethod) {
LocaleContextHolder.setLocaleContext(new LocaleContext() {
public Locale getLocale() {
Lang preferred = Lang.preferred(request.acceptLanguages());
return preferred.toLocale();
}
});
return super.onRequest(request, actionMethod);
}
}
Does someone have a solution to this problem? Is it a known bug in Play? I'm using version 2.0.4.
Thanks!
I tried estmatic's solution, but it didn't discriminate properly between country variants of the same language, for example if my browser's preferred languages were "en_AU" and "en_US" in that order, then it would only use the "en" part, which resulted in a US-style date (with the month first) rather than an Aussie-style one (with the date first, as is right and proper).
My solution was to create a helper class as follows:
public class Formatter extends Controller {
private static final int DATE_STYLE = LONG;
private static final int TIME_STYLE = SHORT;
/**
* Formats the given Date as a date and time, using the locale of the current
* request's first accepted language.
*
* #param date the date to format (required)
* #return the formatted date
* #see play.mvc.Http.Request#acceptLanguages()
*/
public static String formatDateTime(final Date date) {
final Locale locale = getPreferredLocale();
return DateFormat.getDateTimeInstance(
DATE_STYLE, TIME_STYLE, locale).format(date);
}
private static Locale getPreferredLocale() {
final List<Lang> acceptedLanguages = request().acceptLanguages();
final Lang preferredLanguage = acceptedLanguages.isEmpty() ?
Lang.preferred(acceptedLanguages) : acceptedLanguages.get(0);
return new Locale(preferredLanguage.language(), preferredLanguage.country());
}
}
Then in my Scala templates, all I had to do was use (for example):
#import my.package.Formatter
...
Date = #Formatter.formatDateTime(someDate)
This seems cleaner to me than having a lot of Locale construction logic in the templates.
Well you need to provide the locale when you get your DateFormat instance; otherwise it'll just use the system default locale instead of what Play is getting from the browser.
Something like this seems to work:
#DateFormat.getDateInstance(DateFormat.LONG, (implicitly[Lang]).toLocale).format(deadline)
That implicitly[Lang] bit is basically calling Lang.preferred(request.acceptLanguages() just like you were doing in your onRequest() method.
I have date in this format 2011-11-02. From this date, how can we know the Day-of-week, Month and Day-of-month, like in this format Wednesday-Nov-02, from calendar or any other way?
If it were normal java, you would use two SimpleDateFormats - one to read and one to write:
SimpleDateFormat read = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat write = new SimpleDateFormat("EEEE-MMM-dd");
String str = write.format(read.parse("2011-11-02"));
System.out.println(str);
Output:
Wednesday-Nov-02
As a function (ie static method) it would look like:
public static String reformat(String source) throws ParseException {
SimpleDateFormat read = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat write = new SimpleDateFormat("EEEE-MMM-dd");
return write.format(read.parse(source));
}
Warning:
Do not be tempted to make read or write into static fields to save instantiating them every method invocation, because SimpleDateFormat is not thread safe!
Edited
However, after consulting the Blackberry Java 5.0 API doc, it seems the write.format part should work with blackberry's SimpleDateFormat, but you'll need to parse the date using something else... HttpDateParser looks promising. I don't have that JDK installed, but try this:
public static String reformat(String source) {
SimpleDateFormat write = new SimpleDateFormat("EEEE-MMM-dd");
Date date = new Date(HttpDateParser.parse(source));
return write.format(date);
}