I have a String with several dates, for example:
[20-Jul-2012 5:11:36,670 UTC PM, 20-Jul-2012 5:11:36,683 UTC PM]
How do I read this string and extract each date? I'm using the SimpleDateFormat class to create a regex.
SimpleDateFormat format2 = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss,SSS z a");
I've tried :
I've just did, to get the first one and it changes the format and the timezone:
ParsePosition parsePos = new ParsePosition(1);
SimpleDateFormat format2 = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss,SSS z a");
System.out.println(format2.parse(entry.getValue().toString(), parsePos)) ;
Output : Fri Jul 20 06:11:36 BST 2012
You can try:
parsePos = new ParsePosition(1);
while((date = format2.parse(yourString, parsePos)!=null){
//use date
}
java.time
The question uses SimpleDateFormat which was the correct thing to do in 2012. In Mar 2014, the java.util date-time API and their formatting API, SimpleDateFormat were supplanted by the modern Date-Time API. Since then, it is strongly recommended to stop using the legacy date-time API.
Solution using the modern date-time API:
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.stream.Stream;
class Main {
public static void main(String[] args) {
DateTimeFormatter parser = DateTimeFormatter.ofPattern("d-MMM-uuuu h:m:s,SSS VV a", Locale.ENGLISH);
Stream.of(
"20-Jul-2012 5:11:36,670 UTC PM",
"20-Jul-2012 5:11:36,683 UTC PM"
)
.map(s -> ZonedDateTime.parse(s, parser))
.forEach(System.out::println);
}
}
Output:
2012-07-20T17:11:36.670Z[UTC]
2012-07-20T17:11:36.683Z[UTC]
ONLINE DEMO
Learn more about the modern Date-Time API from Trail: Date Time.
Related
I have this String date="2021-04-25T18:54:18" and i should to format like that: HH:mm ,dd mmm yyyy
I tried this
String date="2021-04-25T18:54:18";
Date format= null;
try {
format = new SimpleDateFormat("HH:mm, yyyy-MM-dd'T", Locale.ENGLISH).parse(date);
holder.tvDate.setText(format.toString());
} catch (ParseException e) {
e.printStackTrace();
}
But does not work
The legacy date-time API (java.util date-time types and their formatting API, SimpleDateFormat) are outdated and error-prone. It is recommended to stop using them completely and switch to java.time, the modern date-time API* .
Using modern date-time API:
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String strDateTime = "2021-04-25T18:54:18";
LocalDateTime ldt = LocalDateTime.parse(strDateTime);
DateTimeFormatter dtfOutput = DateTimeFormatter.ofPattern("HH:mm ,dd MMM yyyy", Locale.ENGLISH);
String output = dtfOutput.format(ldt);
System.out.println(output);
}
}
Output:
18:54 ,25 Apr 2021
Learn more about the modern date-time API from Trail: Date Time.
Using the legacy API:
You need two formatters: one for input pattern and one for output pattern. You didn't need two formatters in the case of the modern API because the modern API is based on ISO 8601 and your date-time string is already in this format.
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class Main {
public static void main(String[] args) throws ParseException {
String strDateTime = "2021-04-25T18:54:18";
SimpleDateFormat sdfInput = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH);
Date date = sdfInput.parse(strDateTime);
SimpleDateFormat sdfOutput = new SimpleDateFormat("HH:mm ,dd MMM yyyy", Locale.ENGLISH);
String output = sdfOutput.format(date);
System.out.println(output);
}
}
Output:
18:54 ,25 Apr 2021
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
You are missing 1 step. SimpleDateFormat can only parse dates in the format you specify.
You are trying to parse a "yyyy-MM-dd ..." based string into the "HH:mm ..." date. This will not work.
First convert your "yyyy-MM-dd" date string into a Date.
Then, format that Date into the String you need
String input = "2021-04-25T18:54:18";
Date date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH).parse(input);
String output = new SimpleDateFormat("HH:mm, yyyy-MM-dd", Locale.ENGLISH).format(date);
Here is my simple code:
String defaultSimpleDateFormatPattern = "MMM dd, yyyy HH:mm:ss";
TimeZone tzNY = TimeZone.getTimeZone("America/New_York");
TimeZone tzLos = TimeZone.getTimeZone("America/Los_Angeles");
String dateToTest = "Jan 03, 2015 23:59:59";
SimpleDateFormat df = new SimpleDateFormat(defaultSimpleDateFormatPattern);
Calendar c = Calendar.getInstance();
c.setTime(df.parse(dateToTest));
c.setTimeZone(tzLos);
System.out.println(c.getTimeZone());
System.out.println(c.getTime());
System.out.println(df.format(c.getTime()));
Calendar c1 = Calendar.getInstance();
c1.setTime(df.parse(dateToTest));
c1.setTimeZone(tzNY);
System.out.println(c1.getTimeZone());
System.out.println(c1.getTime());
System.out.println(df.format(c1.getTime()));
System.out.println(c.after(c1)? "after" : (c.before(c1)? "before" : "equal"));
The printout is "equal". How is that? any explanation on this result?
There are two problems here:
You're using an invalid time zone ID (you want America/New_York)
You're parsing using a formatter that hasn't got a time zone set (so it'll use the default time zone) and then setting the time zone in the Calendar afterwards... that doesn't change the instant in time being represented
So basically you're parsing to the same Date twice, doing things which don't affect the Date being represented, and then comparing the two equal Date values.
If at all possible, you should use Joda Time or java.time instead of java.util.Calendar, but if you really need to use it, just create two different formatters, one with each time zone. (You'll need to set the time zone in the Calendar as well, if you actually need the Calendar...)
java.time
The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.
Also, quoted below is a notice from the home page of Joda-Time:
Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this project.
Solution using java.time, the modern Date-Time API: Your Date-Time string does not have timezone information and therefore it can be described as a local Date-Time. So, parse it to LocalDateTime and apply the timezone to it to get the ZonedDateTime.
Demo:
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String defaultSimpleDateFormatPattern = "MMM dd, uuuu HH:mm:ss";
ZoneId tzNY = ZoneId.of("America/New_York");
ZoneId tzLos = ZoneId.of("America/Los_Angeles");
String dateToTest = "Jan 03, 2015 23:59:59";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern(defaultSimpleDateFormatPattern, Locale.ENGLISH);
LocalDateTime ldt = LocalDateTime.parse(dateToTest, dtf);
ZonedDateTime zdtNY = ldt.atZone(tzNY);
ZonedDateTime zdtLos = ldt.atZone(tzLos);
System.out.println(zdtNY.isAfter(zdtLos) ? "after" : zdtNY.isBefore(zdtLos) ? "before" : "equal");
}
}
Output:
before
ONLINE DEMO
Alternatively, Create separate DateTimeFormatter specific to each timezone i.e. ask Java to parse the local Date-Time string applying the given timezone.
Demo:
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String defaultSimpleDateFormatPattern = "MMM dd, uuuu HH:mm:ss";
ZoneId tzNY = ZoneId.of("America/New_York");
ZoneId tzLos = ZoneId.of("America/Los_Angeles");
String dateToTest = "Jan 03, 2015 23:59:59";
DateTimeFormatter dtfNY = DateTimeFormatter.ofPattern(defaultSimpleDateFormatPattern, Locale.ENGLISH)
.withZone(tzNY);
DateTimeFormatter dtfLos = DateTimeFormatter.ofPattern(defaultSimpleDateFormatPattern, Locale.ENGLISH)
.withZone(tzLos);
ZonedDateTime zdtNY = ZonedDateTime.parse(dateToTest, dtfNY);
ZonedDateTime zdtLos = ZonedDateTime.parse(dateToTest, dtfLos);
System.out.println(zdtNY.isAfter(zdtLos) ? "after" : zdtNY.isBefore(zdtLos) ? "before" : "equal");
}
}
Output:
before
ONLINE DEMO
Learn more about the modern Date-Time API from Trail: Date Time.
What is wrong with your code?
You have not set a timezone to your SimpleDateFormat: Unlike the modern Date-Time API with which you have multiple ways to create a Date-Time object specific to a timezone, you have only this way with the legacy API to deal with such a situation (because java.util.Date does not hold timezone information). It is similar to the alternative example shown above.
You have not set a Locale to your SimpleDateFormat: Never use SimpleDateFormat or DateTimeFormatter without a Locale. Luckily, your program did not crash because your JVM's timezone must be an English locale.
Demo:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;
public class Main {
public static void main(String[] args) throws ParseException {
String defaultSimpleDateFormatPattern = "MMM dd, yyyy HH:mm:ss";
TimeZone tzNY = TimeZone.getTimeZone("America/New_York");
TimeZone tzLos = TimeZone.getTimeZone("America/Los_Angeles");
String dateToTest = "Jan 03, 2015 23:59:59";
SimpleDateFormat df = new SimpleDateFormat(defaultSimpleDateFormatPattern, Locale.ENGLISH);
df.setTimeZone(tzNY);
Calendar c = Calendar.getInstance();
c.setTime(df.parse(dateToTest));
df.setTimeZone(tzLos);
Calendar c1 = Calendar.getInstance(tzNY);
c1.setTime(df.parse(dateToTest));
System.out.println(c.after(c1) ? "after" : (c.before(c1) ? "before" : "equal"));
}
}
Output:
before
ONLINE DEMO
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
I am getting the strangest error, when trying to parse a string as a calendar.
It seems that it messes up the Date object which I use to set the result calendar's time. The error is pretty inconsistent (or I see no logic in it). Can anyone point out what I might be doing wrong ?
public class caltest{
public static final SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss.SSS");
public static void main(String[] args) {
String date1 = "1992-03-11 12:00:12.123";
String date2 = "1993-03-11 12:00:12.123";
String date3 = "1994-03-11 12:00:12.123";
String date4 = "1995-03-11 12:00:12.123";
parseStringAsCalendar(date1);
parseStringAsCalendar(date2);
parseStringAsCalendar(date3);
parseStringAsCalendar(date4);
}
public static String calendarToString(Calendar cal) {
return sdf.format(cal.getTime());
}
public static Calendar parseStringAsCalendar(String s) {
Date time = null;
try {
time = sdf.parse(s);
} catch (ParseException e) {
System.out.println("Exception");
e.printStackTrace();
}
System.out.println(time.toString());
GregorianCalendar ret = new GregorianCalendar();
ret.setTime(time);
return ret;
}
}
The output is :
Sun Dec 29 12:00:12 CET 1991
Sun Dec 27 12:00:12 CET 1992
Sun Dec 26 12:00:12 CET 1993
Sun Jan 01 12:00:12 CET 1995
You're using YYYY in your format specifier, which is week year (as of Java 7, I believe). You want yyyy, which is just "year". (See the SimpleDateFormat documentation.)
I suspect the rest of the date was out because you tried to also specify the month and day, which aren't really "features" in the week year... if you'd specified the "week of week year" and day of week, it might have given some more sensible results, but only if you really meant to use week years, which I doubt :)
Use this:
public static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
It's lower case y for year, not upper case Y. With that, the result is:
Wed Mar 11 12:00:12 EST 1992
Thu Mar 11 12:00:12 EST 1993
Fri Mar 11 12:00:12 EST 1994
Sat Mar 11 12:00:12 EST 1995
See here:
http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
java.time
The question and existing answers use SimpleDateFormat which was the correct thing to do in 2012. In Mar 2014, the java.util date-time API and their formatting API, SimpleDateFormat were supplanted by the modern Date-Time API. Since then, it is strongly recommended to stop using the legacy date-time API.
Solution using the modern date-time API: As you can learn from the documentation, the symbol Y is used for week-based-year whereas we need y (year-of-era) in this case. However, I prefer u to y.
Note that your date-time string has just date and time units (no time-zone or time-zone offset etc.). The java.time API provides you with LocalDateTime to represent such an object.
In case, you need to obtain a date-time object with time-zone or one representing just a moment in time, java.time provides you with specific types. You can check overview of java.time types here.
With Java 8, java.util date-time API was also upgraded to make it easy to switch to java.time API e.g. if you need java.util.Date instance from a an Instant, you can use Date#from.
Demo:
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.Date;
import java.util.Locale;
class Main {
public static void main(String[] args) {
String strDateTime = "1992-03-11 12:00:12.123";
DateTimeFormatter parser = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSS", Locale.ENGLISH);
// An alternative parser
DateTimeFormatter ldtParser = new DateTimeFormatterBuilder().append(DateTimeFormatter.ISO_LOCAL_DATE)
.appendLiteral(' ').append(DateTimeFormatter.ISO_LOCAL_TIME).toFormatter(Locale.ENGLISH);
LocalDateTime ldt = LocalDateTime.parse(strDateTime, parser);
System.out.println(ldt);
// Parsing using the alternative parser
ldt = LocalDateTime.parse(strDateTime, ldtParser);
System.out.println(ldt);
// Converting LocalDateTime to a ZonedDateTime
// Replace ZoneId.systemDefault() with applicable ZoneId e.g.
// ZoneId.of("America/New_York")
ZoneId zoneId = ZoneId.systemDefault();
ZonedDateTime zdt = ldt.atZone(zoneId);
System.out.println(zdt);
// Alternatively,
zdt = ZonedDateTime.of(ldt, zoneId);
System.out.println(zdt);
// Obtaining an Instant
Instant instant = zdt.toInstant();
System.out.println(instant);
// In case you need an instance of java.util.Date
Date date = Date.from(instant);
}
}
Output in my time-zone, Europe/London:
1992-03-11T12:00:12.123
1992-03-11T12:00:12.123
1992-03-11T12:00:12.123Z[Europe/London]
1992-03-11T12:00:12.123Z[Europe/London]
1992-03-11T12:00:12.123Z
ONLINE DEMO
Learn more about the modern Date-Time API from Trail: Date Time.
Note: Check this answer and this answer to learn how to use java.time API with JDBC.
These lines of codes
SimpleDateFormat formatter = new SimpleDateFormat("dd/mm/yy");
ContentValues values = new ContentValues();
values.put(COL_EVENT_ID, appointment.mEventId);
try {
values.put(COL_START_DATE, String.valueOf(formatter.parse(appointment.mStartDate.toString())));
values.put(COL_END_DATE, String.valueOf(formatter.parse(appointment.mEndDate.toString())));
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
causees this exception
10-15 11:44:38.150: WARN/System.err(3861): java.text.ParseException: Unparseable date: "Mon Jan 10 00:10:00 GMT+02:00 2011"
what is the possible solution ?
Your format is completely wrong. Not only are you using mm (which means minutes) when you probably meant MM, but this:
Mon Jan 10 00:10:00 GMT+02:00 2011
is clearly not in the format
dd/MM/yy
You probably want something like
EEE MMM dd HH:mm:ss z yyyy
EDIT: That works for me in desktop Java:
import java.text.*;
public class Test {
public static void main(String[] args) throws ParseException {
String value = "Mon Jan 10 00:10:00 GMT+02:00 2011";
String pattern = "EEE MMM dd HH:mm:ss z yyyy";
DateFormat format = new SimpleDateFormat(pattern);
System.out.println(format.parse(value));
}
}
You may want to set the culture of the SimpleDateFormat of course.
java.time
The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.
Solution using java.time, the modern Date-Time API:
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String strDateTime = "Mon Jan 10 00:10:00 GMT+02:00 2011";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEE MMM d H:m:s OOOO uuuu", Locale.ENGLISH);
ZonedDateTime zdt = ZonedDateTime.parse(strDateTime, dtf);
System.out.println(zdt);
}
}
Output:
ONLINE DEMO
Notes:
m specifies minute-of-hour whereas M specifies month-of-year. You have wrongly used the former.
The pattern used with the parser (DateTimeFormatter or SimpleDateFormat) should match the input date-time string. Your pattern, dd/mm/yy is off by far.
Never use SimpleDateFormat or DateTimeFormatter without a Locale.
Learn more about the modern Date-Time API from Trail: Date Time.
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
I have a string named DateCompareOld, it has the value "Fri Aug 12 16:08:41 EDT 2011". I want to convert this to a date object.
SimpleDateFormat dateType = new SimpleDateFormat("E M dd H:m:s z yyyy");
Date convertDate = dateType.parse(DateCompareOld);
But everytime I try this, I get a parse exception. I have tried other SimpleDateFormat formatting criteria, but it always fails.
Suggestions?
Try this format:
EEE MMM dd HH:mm:ss zzz yyyy
Quick test:
public static void main(String[] args) throws Exception {
DateFormat df = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy");
System.out.println(df.parse("Fri Aug 12 16:08:41 EDT 2011"));
}
// outputs
Fri Aug 12 15:08:41 CDT 2011
Output is in CDT, since that's where I am, but the value is right.
DateFormat dateType = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy");
dateType.setLenient(false);
Date convertDate = dateType.parse(DateCompareOld);
java.time
The legacy date-time API (java.util date-time types and their formatting API, SimpleDateFormat) are outdated and error-prone. It is recommended to stop using them completely and switch to java.time, the modern date-time API*.
Another important thing to note is that your string has English text and therefore you must use Locale.ENGLISH so that you do not get an exception or some wrong result when your code is run on a JVM whose Locale is not English. Anyway, NEVER use a date-time parsing/formatting type (e.g. SimpleDateFormat, DateTimeFormatter etc.) without Locale because these types are Locale-sensitive.
Demo using modern date-time API:
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String args[]) {
String strDateTime = "Fri Aug 12 16:08:41 EDT 2011";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("E MMM d H:m:s z u", Locale.ENGLISH);
ZonedDateTime zdt = ZonedDateTime.parse(strDateTime, dtf);
System.out.println(zdt);
}
}
Output:
2011-08-12T16:08:41-04:00[America/New_York]
If at all, you need a java.util.Date object, you can obtain it as follows:
Date date = Date.from(zdt.toInstant());
Learn more about the modern date-time API from Trail: Date Time.
Using the legacy API:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class Main {
public static void main(String args[]) throws ParseException {
String strDateTime = "Fri Aug 12 16:08:41 EDT 2011";
SimpleDateFormat sdf = new SimpleDateFormat("E MMM d H:m:s z y", Locale.ENGLISH);
Date date = sdf.parse(strDateTime);
// ...
}
}
Note that the java.util.Date object is not a real date-time object like the modern date-time types; rather, it represents the number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT (or UTC). When you print an object of java.util.Date, its toString method returns the date-time in the JVM's timezone, calculated from this milliseconds value. If you need to print the date-time in a different timezone, you will need to set the timezone to SimpleDateFormat and obtain the formatted string from it.
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
Note the String passed to SimpleDateFormat() should be corrected to "EEE MMM dd HH:mm:ss z yyyy"
Here is the code:
import java.util.Date;
import java.text.SimpleDateFormat;
import java.text.ParseException;
public class DateTest{
public static void main(String []args){
String DateCompareOld = "Fri Aug 12 16:08:41 EDT 2011";
SimpleDateFormat dateType = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy");
Date convertDate = new Date();
try{
convertDate = dateType.parse(DateCompareOld);
}catch(ParseException pex){
pex.printStackTrace();
}
System.out.println(convertDate.toString());
}
}