I am trying to convert Json date string to java date format. However, it gives error when it comes to "return df.parse( tarih )" line.
JSON :
{"DateFrom":"\/Date(1323087840000+0200)\/"}
Java code :
private Date JSONTarihConvert(String tarih) throws ParseException
{
SimpleDateFormat df = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ssz" );
if ( tarih.endsWith( "Z" ) ) {
tarih = tarih.substring( 0, tarih.length() - 1) + "GMT-00:00";
} else {
int inset = 6;
String s0 = tarih.substring( 6, tarih.length()-1 - inset );
String s1 = tarih.substring( tarih.length()- inset,tarih.length()-2 );
tarih = s0 + "GMT" + s1;
}
return df.parse( tarih );
}
When I call this method, tarih parameter is: /Date(1323087840000+0200)/
As you're interested in a Date object and the JSON occurs to me to be a unix timestamp.
Therefore I'd recommend you the Date(long milliseconds) constructor :)
private Date JSONTarihConvert(String tarih) throws ParseException{
long timestamp = getTimeStampFromTarih(tarih);
return new Date(timestamp);
}
Where getTimeStampFromTarih extracts the milliseconds before the occurrence of "+"
This will work surely
String date = "/Date(1376841597000)/";
Calendar calendar = Calendar.getInstance();
String datereip = date.replace("/Date(", "").replace(")/", "");
Long timeInMillis = Long.valueOf(datereip);
calendar.setTimeInMillis(timeInMillis);
System.out.println(calendar.getTime().toString("dd-MMM-yyyy h:mm tt"));//It Will Be in format 29-OCT-2014 2:26 PM
First replace string like this :
String str= ConvertMilliSecondsToFormattedDate(strDate.replace("/Date(","").replace(")/", ""));
Then Convert it like this:
public static String ConvertMilliSecondsToFormattedDate(String milliSeconds){
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(Long.parseLong(milliSeconds));
return simpleDateFormat.format(calendar.getTime());
}
You will Need to type cast date:
String rawdate = "/Date(1995769286000)/";
Calendar calendarins = Calendar.getInstance();
String datereip = rawdate.replace("/Date(", "").replace(")/", "");
Long timeInMillis = Long.valueOf(datereip);
calendar.setTimeInMillis(timeInMillis);
System.out.println(calendar.getTime().toString("dd-MMM-yyyy h:mm tt"));
Unless you have a reason not to, you should be using a parser to serialize and de-serialize objects. Like Jackson parser.
java.time
This is the modern answer (since 2014).
First I want to make sure the timestamp I have really lives up to the format I expect. I want to make sure if one day it doesn’t, I don’t just pretend and the user will get incorrect results without knowing they are incorrect. So for parsing the timestamp string, since I didn’t find a date-time format that would accept milliseconds since the epoch, I used a regular expression:
String time = "/Date(1479974400000-0800)/";
Pattern pat = Pattern.compile("/Date\\((\\d+)([+-]\\d{4})\\)/");
Matcher m = pat.matcher(time);
if (m.matches()) {
Instant i = Instant.ofEpochMilli(Long.parseLong(m.group(1)));
System.out.println(i);
}
This prints:
2016-11-24T08:00:00Z
It is not clear to me whether you need to use the zone offset and for what purpose. But since we’ve got it, why not retrieve it from the matcher and use it for forming an OffsetDateTime, a date and time with UTC offset. Here’s how:
ZoneOffset zo = ZoneOffset.of(m.group(2));
OffsetDateTime odt = OffsetDateTime.ofInstant(i, zo);
System.out.println(odt);
2011-12-05T14:24+02:00
If you need an old-fashioned java.util.Date for some legacy API:
System.out.println(Date.from(i));
Or if using the backport mentioned in the links below:
System.out.println(DateTimeUtils.toDate(i));
On my computer it prints
Mon Dec 05 13:24:00 CET 2011
The exact output will depend on your time zone.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.time to Java 6 and 7 (ThreeTen for JSR-310).
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
Related
I am trying to parse a String with a date into a Date object and then convert it into millis.
But whatever I am doing - the output result in millis is always lower in 2 hours than the input date.
For example if the input date is 2018-1-10 11:30 - the output date will be 2018-01-10 9:30.
This is my code:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
String dateString = "2018-1-10 11:30";
Date resultDate = sdf.parse(dateString);
long millis = resultDate.getTime();
// millis = 1515576600000
// When i am trying to convert millis to normal date via online
// converters i am always getting
// this result 10.01.18 9:30
I cannot understand why this is happening. How can I get back valid result after converting millis back? Why I got this difference in two hours?
It looks like a timezone problem.
Check in which timezone you are. If you are in UTC +02:00 the result is good !
If you want to set manually the timezone to match with UTC (without offset), check this stack overflow question: How to set time zone of a java.util.Date?
I hope this help you :)
One more example of where java.time, the modern Java date and time API, excels. It forces you to specify zone offset or time zone for operations like this one, which solves the problem:
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-M-d H:mm");
String dateString = "2018-1-10 11:30";
long epochMillis = LocalDateTime.parse(dateString, dtf)
.atOffset(ZoneOffset.UTC)
.toInstant()
.toEpochMilli();
The result is 1515583800000 (maybe more readable as 1 515 583 800 000). Remove the last three zeros to convert to seconds and enter them on, for example, http://www.onlineconversion.com/unix_time.htm. The result is:
Wed, 10 Jan 2018 11:30:00 GMT
The GMT in the end confirms that the time is at the expected offset (for now we can consider GMT and UTC equivalent).
Question: Can I use java.time on Android?
You certainly can (I haven’t got the experience myself, though).
For the general Android market, use the Android edition of ThreeTen Backport (mentioned below). It’s called ThreeTenABP. Then import org.threeten.bp.format.DateTimeFormatter and org.threeten.bp.LocalDateTime.
For a newer Android device with Java 8 it should work out-of-the-box if you import java.time.format.DateTimeFormatter and java.time.LocalDateTime.
And on non-Android Java?
In Java 8 and later the new API comes built-in.
In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310).
Links
Oracle tutorial: Date Time, explaining how to use java.time.
ThreeTen Backport project
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
Java Specification Request (JSR) 310, where the modern date and time API was first described.
By parsing the string it is assumed that the given time is based on your local time, whereas Date is in UTC. SimpleDateFormat does the conversion for you using your pcs time zone if you don't specify it.
https://docs.oracle.com/javase/7/docs/api/java/text/DateFormat.html#setTimeZone(java.util.TimeZone)
https://docs.oracle.com/javase/8/docs/api/java/util/Date.html
To convert it back you should use new Date (millis)
This considers your timezone as well and your result should be correct.
I think you are aware now that it is a timezone issue, but I figured I'll supply you a helper class that I wrote and use in most my applications as client server applications always have to take in account timezones and should be storing GMT on the server.
Hope this helps, you can copy and paste this class and handle a lot of your date formatting and timezone issues to and from the server.
public class DateHelper {
/*///////////////////////////////////////////////////////////////
// MEMBERS
*////////////////////////////////////////////////////////////////
public static SimpleDateFormat MY_APPS_CUSTOM_FORMATTER;
public final static String MMMM_dd = "MMMM, dd";
public final static String MMM_dd_yyyy = "MMM dd yyyy";
public final static String MMSlashddSlashyy = "MM/dd/yy";
public final static String MMSlashddSlashyy_hhColonmm_a = "MM/dd/yy hh:mm a";
public final static Calendar mCalender = Calendar.getInstance();
public final static TimeZone mLocalTimezone = mCalender.getTimeZone();
/*///////////////////////////////////////////////////////////////
// PROPERTIES
*////////////////////////////////////////////////////////////////
public synchronized static SimpleDateFormat getMyAppsDateCustomFormatter(boolean toServer, String format){
MY_APPS_CUSTOM_FORMATTER = new SimpleDateFormat(format);
if(toServer){
MY_APPS_CUSTOM_FORMATTER.setTimeZone(TimeZone.getTimeZone("UTC"));
}else{
MY_APPS_CUSTOM_FORMATTER.setTimeZone(mLocalTimezone);
}
return MY_APPS_CUSTOM_FORMATTER;
}
/*///////////////////////////////////////////////////////////////
// EXTRA HELPER METHODS
*////////////////////////////////////////////////////////////////
public static String getNowLocalTime(String formatToReturn){
return getMyAppsDateCustomFormatter(false, formatToReturn).format(new Date());
}
/*///////////////////////////////////////////////////////////////
// FROM SERVER FORMATTING
*////////////////////////////////////////////////////////////////
public static String getLocalDateStringFromGMTLong(long gmtTimestamp, String formatToReturn){
return getMyAppsDateCustomFormatter(false, formatToReturn).format(new Date(gmtTimestamp * 1000));
}
public static Date getDateFromLocalFormattedString(String date, String formatToUse, boolean toServer) throws Exception{
Date parsedDate = null;
try {
parsedDate = getMyAppsDateCustomFormatter(toServer, formatToUse).parse(date);
} catch (ParseException e) { //developer error, do NOT localize
throw new Exception(Globals.DEV_ERROR_STRINGS.INVALID_DATE_SUPPLIED_FOR_DEFAULT_FORMATTER);
}
return parsedDate;
}
public static String getFormattedStringFromLocalDate(Date date, String formatToUse) throws Exception{
return getMyAppsDateCustomFormatter(false, formatToUse).format(date);
}
/*///////////////////////////////////////////////////////////////
// TO SERVER FORMATTING
*////////////////////////////////////////////////////////////////
public static long getGMTLongFromLocalDate(Date date){
//Get Local Timezone
TimeZone tz = TimeZone.getDefault();
//Create new date for offset to GMT
Date ret = new Date(date.getTime() - tz.getRawOffset() );
// if we are now in DST, back off by the delta. Note that we are checking the GMT date, this is the KEY.
if ( tz.inDaylightTime( ret )){
Date dstDate = new Date( ret.getTime() - tz.getDSTSavings() );
// check to make sure we have not crossed back into standard time
// this happens when we are on the cusp of DST (7pm the day before the change for PDT)
if ( tz.inDaylightTime( dstDate )){
ret = dstDate;
}
}
return ret.getTime();
}
public static long getGMTLongFromLocalDateString(String date, String formatUsed) throws Exception {
Date passedDate = getDateFromLocalFormattedString(date, formatUsed, true);
//Get Local Timezone
TimeZone tz = TimeZone.getDefault();
//Create new date for offset to GMT
Date ret = new Date(passedDate.getTime() - tz.getRawOffset() );
// if we are now in DST, back off by the delta. Note that we are checking the GMT date, this is the KEY.
if ( tz.inDaylightTime( ret )){
Date dstDate = new Date( ret.getTime() - tz.getDSTSavings() );
// check to make sure we have not crossed back into standard time
// this happens when we are on the cusp of DST (7pm the day before the change for PDT)
if ( tz.inDaylightTime( dstDate )){
ret = dstDate;
}
}
return ret.getTime() / 1000;
}
public static long getNowGMTTime(){
return getGMTLongFromLocalDate(new Date());
}
}
There is a call to some external system which returns a date in hijri. In Production env, we received it as '30-02-1436'.
Consider the snippet which converts the hijri to a gregorian date, but it fails to do so.
public static String convertHijriToGregorianDate(String hijriDate){
Chronology iso = ISOChronology.getInstanceUTC(); // get the ISO standard chronology which we follow now
Chronology hijri = IslamicChronology.getInstanceUTC(); // the hijri based chronology
//String hijriDate = "19-08-1435"; // example/format which is received as a parameter in the method from response
if(null != hijriDate && !hijriDate.isEmpty()){
String[] parts = hijriDate.trim().split("-"); // you will get an array of size 3 by splitting with regex '-'
String hijriYear = parts[2];
String hijriMonth = parts[1];
String hijriDay = parts[0];
// Construct the Local Date corresponding to the hijri chronology
LocalDate todayHijri = new LocalDate(Integer.parseInt(hijriYear), Integer.parseInt(hijriMonth), Integer.parseInt(hijriDay), hijri);
// Construct the Local Date corresponding to the iso chronology based on the hijri date
LocalDate todayIso = new LocalDate(todayHijri.toDateTimeAtStartOfDay(), iso);
return String.valueOf(todayIso);
}
return null;
}
Please suggest as to what is wrong with the code. We are getting this issue in stacktrace-
org.joda.time.IllegalFieldValueException: Value 30 for dayOfMonth must
be in the range [1,29]
at org.joda.time.field.FieldUtils.verifyValueBounds(FieldUtils.java:252)
at org.joda.time.chrono.BasicChronology.getDateMidnightMillis(BasicChronology.java:632)
at org.joda.time.chrono.BasicChronology.getDateTimeMillis0(BasicChronology.java:186)
at org.joda.time.chrono.BasicChronology.getDateTimeMillis(BasicChronology.java:160)
at org.joda.time.chrono.LimitChronology.getDateTimeMillis(LimitChronology.java:177)
at org.joda.time.chrono.BasicChronology.getDateTimeMillis(BasicChronology.java:155)
at org.joda.time.LocalDate.(LocalDate.java:457)
Joda time version used is 2.9.1
I have checked all available leap year patterns (=4) in Joda-Time by the expression
Chronology hijri =
IslamicChronology.getInstance(DateTimeZone.UTC, IslamicChronology.LEAP_YEAR_15_BASED);
Unfortunately nothing works for you. However, the umalqura-calendar of Saudi-Arabia considers '30-02-1436' as valid. It corresponds to the gregorian date 2014-12-22.
Joda-Time does not support this variant of islamic calendar so you cannot do anything here unless you are willing to migrate to Java-8 which contains the umalqura-variant.
System.out.println(HijrahDate.of(1436, 2, 30)); // Hijrah-umalqura AH 1436-02-30
DateTimeFormatter fh =
DateTimeFormatter.ofPattern(
"dd-MM-yyyy",
Locale.forLanguageTag("en")
).withChronology(HijrahChronology.INSTANCE);
System.out.println(HijrahDate.from(fh.parse(input)));
// Hijrah-umalqura AH 1436-02-30
System.out.println(LocalDate.from(HijrahDate.from(fh.parse(input))));
// 2014-12-22
Note: The unicode extension Locale.forLanguageTag("en-u-ca-islamic-umalqura") does unfortunately not seem to work in my experiments so specifying the chronology explicitly is necessary.
Alternative:
If you cannot migrate to Java-8 or even need more features of islamic calendar (for example other variants like those used in Joda-Time) then you might also try out my library Time4J:
String input = "30-02-1436";
ChronoFormatter<HijriCalendar> hf =
ChronoFormatter.ofPattern(
"dd-MM-yyyy",
PatternType.CLDR,
Locale.ROOT,
HijriCalendar.family()
).withCalendarVariant(HijriCalendar.VARIANT_UMALQURA).with(Leniency.STRICT);
System.out.println(hf.parse(input)); // AH-1436-02-30[islamic-umalqura]
System.out.println(hf.parse(input).transform(PlainDate.axis())); // 2014-12-22
The date is interpreted as Feb 30, but this month must have fewer than 30 days in it. This explains the error message. So correct the input so it corresponds to a date that is possible.
I need to convert "11/17" string date (November 2017) to "2017-11-01" (November 1, 2017).
What is the best way to achieve this in Java?
I tried:
String dayMonthYear = "11/17";
dayMonthYear = "01/" + dayMonthYear;
DateTimeFormatter formatter = DateTimeFormat.forPattern("dd/MM/yy");
DateTime dt = formatter.parseDateTime(dayMonthYear);
dt.year().setCopy(dt.getYear() + 2000);
DateTimeFormatter dtfOut = DateTimeFormat.forPattern("yyyy-MM-dd");
dayMonthYear = dtfOut.print(dt);
System.out.println(dayMonthYear); // "2017-11-01";
And:
SimpleDateFormat dateFormatTwoDigitsYear = new SimpleDateFormat(TWO_DIGITS_YEAR_DATE_FORMAT); //"dd/MM/yy"
SimpleDateFormat dateFormatFourDigitsYear = new SimpleDateFormat(FOUR_DIGITS_YEAR_DATE_FORMAT);// "yyyy-MM-dd"
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.YEAR, -100);//??? I AM NOT SURE WHY DO I NEEED THIS??
dateFormatTwoDigitsYear.set2DigitYearStart(calendar.getTime());
try
{
dayMonthYear = dateFormatFourDigitsYear.format(dateFormatTwoDigitsYear.parse(dayMonthYear));
}
catch (ParseException e)
{
log.error("Error while formatting date in yyyy-MM-dd format. Date is " + dayMonthYear);
}
I am not sure why I need this line in second appproach:
calendar.add(Calendar.YEAR, -100);
Both of them are working. But I am not sure if there is better solution.
You don't need to add values to the year. The 2 digit value (17) is automatically ajusted to 2017. Also, there's no need to append day 1 in the input. When the day is not present, SimpleDateFormat automatically sets to 1:
// input format: MM/yy
SimpleDateFormat parser = new SimpleDateFormat("MM/yy");
// output format: yyyy-MM-dd
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
System.out.println(formatter.format(parser.parse("11/17"))); // 2017-11-01
PS: if you need to set to another day (other than 1), you can set the date to a Calendar and change it before formatting:
// parse the date
Date date = parser.parse("11/17");
// set to a Calendar
Calendar cal = Calendar.getInstance();
cal.setTime(date);
// change to whatever day you want
cal.set(Calendar.DAY_OF_MONTH, whateverDayIwant);
// format it
System.out.println(formatter.format(cal.getTime()));
Joda-Time
The old classes (Date, Calendar and SimpleDateFormat) have lots of problems and design issues, and they're being replaced by the new APIs.
I've seen you're using Joda-Time, so here's how to do it with this API.
In Joda-Time, when you parse to a DateTime, it sets default values for all the missing fields (in this case, day, hour, minute, etc). But this API has lots of other types that can suit best for each use case.
As the input has only month and year, you can parse it to a org.joda.time.YearMonth and then set the day to 1. This will create a org.joda.time.LocalDate, which can be printed directly (as the toString() method already returns the date in the format you want):
DateTimeFormatter parser = DateTimeFormat.forPattern("MM/yy");
// parse to YearMonth
YearMonth ym = YearMonth.parse("11/17", parser);
// set day to 1
System.out.println(ym.toLocalDate(1)); // 2017-11-01
I prefer this approach because you can set it to whatever day you want, and don't need to create a full DateTime object with fields that you don't need/care about (such as hour, minutes, etc).
If you need to store this value in a String, just call the toString() method:
// store "2017-11-01" in a String
String output = ym.toLocalDate(1).toString();
The format yyyy-MM-dd is the default used by toString(). If you need a different format, you can pass it to toString():
// convert to another format (example: dd/MM/yyyy)
String output = ym.toLocalDate(1).toString("dd/MM/yyyy"); // 01/11/2017
Or you can use another DateTimeFormatter:
// convert to another format (example: dd/MM/yyyy)
DateTimeFormatter fmt = DateTimeFormat.forPattern("dd/MM/yyyy");
String output = fmt.print(ym.toLocalDate(1)); // 01/11/2017
PS: dt.year().setCopy returns a new object, and as you don't assign it to any variable, this value is lost - this method doesn't change the original DateTime object, so dt is not changed by its line of code.
Java new date/time API
Joda-Time is in maintainance mode and is being replaced by the new APIs, so I don't recommend start a new project with it. Even in joda's website it says: "Note that Joda-Time is considered to be a largely “finished” project. No major enhancements are planned. If using Java SE 8, please migrate to java.time (JSR-310).".
If you can't (or don't want to) migrate from Joda-Time to the new API, you can ignore this section.
If you're using Java 8, consider using the new java.time API. It's easier, less bugged and less error-prone than the old APIs.
If you're using Java 6 or 7, you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, you'll also need the ThreeTenABP (more on how to use it here).
The code below works for both.
The only difference is the package names (in Java 8 is java.time and in ThreeTen Backport (or Android's ThreeTenABP) is org.threeten.bp), but the classes and methods names are the same.
The code is very similar to Joda-Time (the API's are not exactly the same, but they have lots of similarities). You can use a Java 8's java.time.format.DateTimeFormatter and parse the input to a java.time.YearMonth (or, in Java 7's ThreeTen Backport, use a org.threeten.bp.format.DateTimeFormatter and parse to a org.threeten.bp.YearMonth):
DateTimeFormatter parser = DateTimeFormatter.ofPattern("MM/yy");
YearMonth ym = YearMonth.parse("11/17", parser);
System.out.println(ym.atDay(1)); // 2017-11-01
If you need to store this value in a String, just call the toString() method:
// store "2017-11-01" in a String
String output = ym.atDay(1).toString();
The format yyyy-MM-dd is the default used by toString(). If you need a different format, you can use another DateTimeFormatter:
// convert to another format (example: dd/MM/yyyy)
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("dd/MM/yyyy");
String output = fmt.format(ym.atDay(1)); // 01/11/2017
You can define two utility methods one converting the string to date and the other converting it back to string.
static Date stringToDate(String string) throws ParseException
{
DateFormat dateFormat = new SimpleDateFormat("MM/yyyy");
return dateFormat.parse(string);
}
static String dateToString(Date date)
{
DateFormat outputFormatter = new SimpleDateFormat("yyyy-MM-dd");
return outputFormatter.format(date);
}
static String formatString(String string)
{
return dateToString(stringToDate(string));
}
//Just call formatString() with your argument
You can combine them if you only intend to convert the first string type to the second type but I like to keep them separate in case I need a date object from string or string directly from a date object.
I have a date in the following format: 2010-03-01T00:00:00-08:00
I have thrown the following SimpleDateFormats at it to parse it:
private static final SimpleDateFormat[] FORMATS = {
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"), //ISO8601 long RFC822 zone
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssz"), //ISO8601 long long form zone
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"), //ignore timezone
new SimpleDateFormat("yyyyMMddHHmmssZ"), //ISO8601 short
new SimpleDateFormat("yyyyMMddHHmm"),
new SimpleDateFormat("yyyyMMdd"), //birthdate from NIST IHE C32 sample
new SimpleDateFormat("yyyyMM"),
new SimpleDateFormat("yyyy") //just the year
};
I have a convenience method that uses those formats like so:
public static Date figureOutTheDamnDate(String wtf) {
if (wtf == null) {
return null;
}
Date retval = null;
for (SimpleDateFormat sdf : FORMATS) {
try {
sdf.setLenient(false)
retval = sdf.parse(wtf);
System.out.println("Date:" + wtf + " hit on pattern:" + sdf.toPattern());
break;
} catch (ParseException ex) {
retval = null;
continue;
}
}
return retval;
}
It seems to hit on the pattern yyyyMMddHHmm but returns the date as Thu Dec 03 00:01:00 PST 2009.
What is the correct pattern to parse this date?
UPDATE: I don't NEED the time zone parsing. I don't anticipate having time sensitive issues moving between zones, but how would I get the "-08:00" zone format to parse????
Unit test:
#Test
public void test_date_parser() {
System.out.println("\ntest_date_parser");
//month is zero based, are you effing kidding me
Calendar d = new GregorianCalendar(2000, 3, 6, 13, 00, 00);
assertEquals(d.getTime(), MyClass.figureOutTheDamnDate("200004061300"));
assertEquals(new GregorianCalendar(1950, 0, 1).getTime(), MyClass.figureOutTheDamnDate("1950"));
assertEquals(new GregorianCalendar(1997, 0, 1).getTime(), MyClass.figureOutTheDamnDate("199701"));
assertEquals(new GregorianCalendar(2010, 1, 25, 15, 19, 44).getTime(), MyClass.figureOutTheDamnDate("20100225151944-0800"));
//my machine happens to be in GMT-0800
assertEquals(new GregorianCalendar(2010, 1, 15, 13, 15, 00).getTime(),MyClass.figureOutTheDamnDate("2010-02-15T13:15:00-05:00"));
assertEquals(new GregorianCalendar(2010, 1, 15, 18, 15, 00).getTime(), MyClass.figureOutTheDamnDate("2010-02-15T18:15:00-05:00"));
assertEquals(new GregorianCalendar(2010, 2, 1).getTime(), MyClass.figureOutTheDamnDate("2010-03-01T00:00:00-08:00"));
assertEquals(new GregorianCalendar(2010, 2, 1, 17, 0, 0).getTime(), MyClass.figureOutTheDamnDate("2010-03-01T17:00:00-05:00"));
}
Output from unit test:
test_date_parser
Date:200004061300 hit on pattern:yyyyMMddHHmm
Date:1950 hit on pattern:yyyy
Date:199701 hit on pattern:yyyyMM
Date:20100225151944-0800 hit on pattern:yyyyMMddHHmmssZ
Date:2010-02-15T13:15:00-05:00 hit on pattern:yyyy-MM-dd'T'HH:mm:ss
Date:2010-02-15T18:15:00-05:00 hit on pattern:yyyy-MM-dd'T'HH:mm:ss
Date:2010-03-01T00:00:00-08:00 hit on pattern:yyyy-MM-dd'T'HH:mm:ss
Date:2010-03-01T17:00:00-05:00 hit on pattern:yyyy-MM-dd'T'HH:mm:ss
JodaTime's DateTimeFormat to rescue:
String dateString = "2010-03-01T00:00:00-08:00";
String pattern = "yyyy-MM-dd'T'HH:mm:ssZ";
DateTimeFormatter dtf = DateTimeFormat.forPattern(pattern);
DateTime dateTime = dtf.parseDateTime(dateString);
System.out.println(dateTime); // 2010-03-01T04:00:00.000-04:00
(time and timezone difference in toString() is just because I'm at GMT-4 and didn't set locale explicitly)
If you want to end up with java.util.Date just use DateTime#toDate():
Date date = dateTime.toDate();
Wait for JDK7 (JSR-310) JSR-310, the referrence implementation is called ThreeTen (hopefully it will make it into Java 8) if you want a better formatter in the standard Java SE API. The current SimpleDateFormat indeed doesn't eat the colon in the timezone notation.
Update: as per the update, you apparently don't need the timezone. This should work with SimpleDateFormat. Just omit it (the Z) in the pattern.
String dateString = "2010-03-01T00:00:00-08:00";
String pattern = "yyyy-MM-dd'T'HH:mm:ss";
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
Date date = sdf.parse(dateString);
System.out.println(date); // Mon Mar 01 00:00:00 BOT 2010
(which is correct as per my timezone)
if you used the java 7, you could have used the following Date Time Pattern. Seems like this pattern is not supported in the Earlier version of java.
String dateTimeString = "2010-03-01T00:00:00-08:00";
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
Date date = df.parse(dateTimeString);
For More information refer to the SimpleDateFormat documentation.
Here's a snippet I used - with plain SimpleDateFormat. Hope somebody else may benefit from it:
public static void main(String[] args) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") {
public StringBuffer format(Date date, StringBuffer toAppendTo, java.text.FieldPosition pos) {
StringBuffer toFix = super.format(date, toAppendTo, pos);
return toFix.insert(toFix.length()-2, ':');
};
};
// Usage:
System.out.println(dateFormat.format(new Date()));
}
Output:
- Usual Output.........: 2013-06-14T10:54:07-0200
- This snippet's Output: 2013-06-14T10:54:07-02:00
Or... better, use a simpler, different, pattern:
SimpleDateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
// Usage:
System.out.println(dateFormat2.format(new Date()));
Output:
- This pattern's output: 2013-06-14T10:54:07-02:00
See the docs for that.
Try this, its work for me:
Date date = javax.xml.bind.DatatypeConverter.parseDateTime("2013-06-01T12:45:01+04:00").getTime();
In Java 8:
OffsetDateTime dt = OffsetDateTime.parse("2010-03-01T00:00:00-08:00");
If you can use JDK 1.7 or higher, try this:
public class DateUtil {
private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
public static String format(Date date) {
return dateFormat.format(date);
}
public static Date parse(String dateString) throws AquariusException {
try {
return dateFormat.parse(dateString);
} catch (ParseException e) {
throw new AquariusException(e);
}
}
}
document: https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
which supports a new Time Zone format "XXX" (e.g. -3:00)
While JDK 1.6 only support other formats for Time Zone, which are "z" (e.g. NZST), "zzzz" (e.g. New Zealand Standard Time), "Z" (e.g. +1200), etc.
tl;dr
OffsetDateTime.parse( "2010-03-01T00:00:00-08:00" )
Details
The answer by BalusC is correct, but now outdated as of Java 8.
java.time
The java.time framework is the successor to both Joda-Time library and the old troublesome date-time classes bundled with the earliest versions of Java (java.util.Date/.Calendar & java.text.SimpleDateFormat).
ISO 8601
Your input data string happens to comply with the ISO 8601 standard.
The java.time classes use ISO 8601 formats by default when parsing/generating textual representations of date-time values. So no need to define a formatting pattern.
OffsetDateTime
The OffsetDateTime class represents a moment on the time line adjusted to some particular offset-from-UTC. In your input, the offset is 8 hours behind UTC, commonly used on much of the west coast of North America.
OffsetDateTime odt = OffsetDateTime.parse( "2010-03-01T00:00:00-08:00" );
You seem to want the date-only, in which case use the LocalDate class. But keep in mind you are discarding data, (a) time-of-day, and (b) the time zone. Really, a date has no meaning without the context of a time zone. For any given moment the date varies around the world. For example, just after midnight in Paris is still “yesterday” in Montréal. So while I suggest sticking with date-time values, you can easily convert to a LocalDate if you insist.
LocalDate localDate = odt.toLocalDate();
Time Zone
If you know the intended time zone, apply it. A time zone is an offset plus the rules to use for handling anomalies such as Daylight Saving Time (DST). Applying a ZoneId gets us a ZonedDateTime object.
ZoneId zoneId = ZoneId.of( "America/Los_Angeles" );
ZonedDateTime zdt = odt.atZoneSameInstant( zoneId );
Generating strings
To generate a string in ISO 8601 format, call toString.
String output = odt.toString();
If you need strings in other formats, search Stack Overflow for use of the java.util.format package.
Converting to java.util.Date
Best to avoid java.util.Date, but if you must, you can convert. Call the new methods added to the old classes such as java.util.Date.from where you pass an Instant. An Instant is a moment on the timeline in UTC. We can extract an Instant from our OffsetDateTime.
java.util.Date utilDate = java.util.Date( odt.toInstant() );
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
Thanks acdcjunior for your solution. Here's a little optimized version for formatting and parsing :
public static final SimpleDateFormat XML_SDF = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.FRANCE)
{
private static final long serialVersionUID = -8275126788734707527L;
public StringBuffer format(Date date, StringBuffer toAppendTo, java.text.FieldPosition pos)
{
final StringBuffer buf = super.format(date, toAppendTo, pos);
buf.insert(buf.length() - 2, ':');
return buf;
};
public Date parse(String source) throws java.text.ParseException {
final int split = source.length() - 2;
return super.parse(source.substring(0, split - 1) + source.substring(split)); // replace ":" du TimeZone
};
};
You can use X in Java 7.
https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
static final SimpleDateFormat DATE_TIME_FORMAT =
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
static final SimpleDateFormat JSON_DATE_TIME_FORMAT =
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
private String stringDate = "2016-12-01 22:05:30";
private String requiredDate = "2016-12-01T22:05:30+03:00";
#Test
public void parseDateToBinBankFormat() throws ParseException {
Date date = DATE_TIME_FORMAT.parse(stringDate);
String jsonDate = JSON_DATE_TIME_FORMAT.format(date);
System.out.println(jsonDate);
Assert.assertEquals(jsonDate, requiredDate);
}
Try setLenient(false).
Addendum: It looks like you're recognizing variously formatted Date strings. If you have to do entry, you might like looking at this example that extends InputVerifier.
Since an example of Apache FastDateFormat(click for the documentations of versions:2.6and3.5) is missing here, I am adding one for those who may need it. The key here is the pattern ZZ(2 capital Zs).
import java.text.ParseException
import java.util.Date;
import org.apache.commons.lang3.time.FastDateFormat;
public class DateFormatTest throws ParseException {
public static void main(String[] args) {
String stringDateFormat = "yyyy-MM-dd'T'HH:mm:ssZZ";
FastDateFormat fastDateFormat = FastDateFormat.getInstance(stringDateFormat);
System.out.println("Date formatted into String:");
System.out.println(fastDateFormat.format(new Date()));
String stringFormattedDate = "2016-11-22T14:30:14+05:30";
System.out.println("String parsed into Date:");
System.out.println(fastDateFormat.parse(stringFormattedDate));
}
}
Here is the output of the code:
Date formatted into String:
2016-11-22T14:52:17+05:30
String parsed into Date:
Tue Nov 22 14:30:14 IST 2016
Note: The above code is of Apache Commons' lang3. The class org.apache.commons.lang.time.FastDateFormat does not support parsing, and it supports only formatting. For example, the output of the following code:
import java.text.ParseException;
import java.util.Date;
import org.apache.commons.lang.time.FastDateFormat;
public class DateFormatTest {
public static void main(String[] args) throws ParseException {
String stringDateFormat = "yyyy-MM-dd'T'HH:mm:ssZZ";
FastDateFormat fastDateFormat = FastDateFormat.getInstance(stringDateFormat);
System.out.println("Date formatted into String:");
System.out.println(fastDateFormat.format(new Date()));
String stringFormattedDate = "2016-11-22T14:30:14+05:30";
System.out.println("String parsed into Date:");
System.out.println(fastDateFormat.parseObject(stringFormattedDate));
}
}
will be this:
Date formatted into String:
2016-11-22T14:55:56+05:30
String parsed into Date:
Exception in thread "main" java.text.ParseException: Format.parseObject(String) failed
at java.text.Format.parseObject(Format.java:228)
at DateFormatTest.main(DateFormatTest.java:12)
If date string is like 2018-07-20T12:18:29.802Z
Use this
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
This question already has answers here:
How to add time to the current time?
(3 answers)
Closed 1 year ago.
I have the following requirement in the project.
I have a input field by name startDate and user enters in the format YYYY-MM-DD HH:MM:SS.
I need to add two hours for the user input in the startDate field. how can i do it.
Thanks in advance
You can use SimpleDateFormat to convert the String to Date. And after that you have two options,
Make a Calendar object and and then use that to add two hours, or
get the time in millisecond from that date object, and add two hours like, (2 * 60 * 60 * 1000)
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// replace with your start date string
Date d = df.parse("2008-04-16 00:05:05");
Calendar gc = new GregorianCalendar();
gc.setTime(d);
gc.add(Calendar.HOUR, 2);
Date d2 = gc.getTime();
Or,
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// replace with your start date string
Date d = df.parse("2008-04-16 00:05:05");
Long time = d.getTime();
time +=(2*60*60*1000);
Date d2 = new Date(time);
Have a look to these tutorials.
SimpleDateFormat Tutorial
Calendar Tutorial
Being a fan of the Joda Time library, here's how you can do it that way using a Joda DateTime:
import org.joda.time.format.*;
import org.joda.time.*;
...
String dateString = "2009-04-17 10:41:33";
// parse the string
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
DateTime dateTime = formatter.parseDateTime(dateString);
// add two hours
dateTime = dateTime.plusHours(2); // easier than mucking about with Calendar and constants
System.out.println(dateTime);
If you still need to use java.util.Date objects before/after this conversion, the Joda DateTime API provides some easy toDate() and toCalendar() methods for easy translation.
The Joda API provides so much more in the way of convenience over the Java Date/Calendar API.
Try this one, I test it, working fine
Date date = null;
String str = "2012/07/25 12:00:00";
DateFormat formatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
date = formatter.parse(str);
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(Calendar.HOUR, 2);
System.out.println(calendar.getTime()); // Output : Wed Jul 25 14:00:00 IST 2012
If you want to convert in your input type than add this code also
formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
str=formatter.format(calendar.getTime());
System.out.println(str); // Output : 2012-07-25 14:00:00
Use the SimpleDateFormat class parse() method. This method will return a Date object. You can then create a Calendar object for this Date and add 2 hours to it.
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = formatter.parse(theDateToParse);
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.add(Calendar.HOUR_OF_DAY, 2);
cal.getTime(); // This will give you the time you want.
//the parsed time zone offset:
DateTimeFormatter dateFormat = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
String fromDateTimeObj = "2011-01-03T12:00:00.000-0800";
DateTime fromDatetime = dateFormat.withOffsetParsed().parseDateTime(fromDateTimeObj);
Basic program of adding two times:
You can modify hour:min:sec as per your need using if else.
This program shows you how you can add values from two objects and return in another object.
class demo
{private int hour,min,sec;
void input(int hour,int min,int sec)
{this.hour=hour;
this.min=min;
this.sec=sec;
}
demo add(demo d2)//demo because we are returning object
{ demo obj=new demo();
obj.hour=hour+d2.hour;
obj.min=min+d2.min;
obj.sec=sec+d2.sec;
return obj;//Returning object and later on it gets allocated to demo d3
}
void display()
{
System.out.println(hour+":"+min+":"+sec);
}
public static void main(String args[])
{
demo d1=new demo();
demo d2=new demo();
d1.input(2, 5, 10);
d2.input(3, 3, 3);
demo d3=d1.add(d2);//Note another object is created
d3.display();
}
}
Modified Time Addition Program
class demo
{private int hour,min,sec;
void input(int hour,int min,int sec)
{this.hour=(hour>12&&hour<24)?(hour-12):hour;
this.min=(min>60)?0:min;
this.sec=(sec>60)?0:sec;
}
demo add(demo d2)
{ demo obj=new demo();
obj.hour=hour+d2.hour;
obj.min=min+d2.min;
obj.sec=sec+d2.sec;
if(obj.sec>60)
{obj.sec-=60;
obj.min++;
}
if(obj.min>60)
{ obj.min-=60;
obj.hour++;
}
return obj;
}
void display()
{
System.out.println(hour+":"+min+":"+sec);
}
public static void main(String args[])
{
demo d1=new demo();
demo d2=new demo();
d1.input(12, 55, 55);
d2.input(12, 7, 6);
demo d3=d1.add(d2);
d3.display();
}
}
This example is a Sum for Date time and Time Zone(String Values)
String DateVal = "2015-03-26 12:00:00";
String TimeVal = "02:00:00";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SimpleDateFormat sdf2 = new SimpleDateFormat("HH:mm:ss");
Date reslt = sdf.parse( DateVal );
Date timeZ = sdf2.parse( TimeVal );
//Increase Date Time
reslt.setHours( reslt.getHours() + timeZ.getHours());
reslt.setMinutes( reslt.getMinutes() + timeZ.getMinutes());
reslt.setSeconds( reslt.getSeconds() + timeZ.getSeconds());
System.printLn.out( sdf.format(reslt) );//Result(+2 Hours): 2015-03-26 14:00:00
Thanks :)
This will give you the time you want (eg: 21:31 PM)
//Add 2 Hours to just TIME
SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss a");
Date date2 = formatter.parse("19:31:51 PM");
Calendar cal2 = Calendar.getInstance();
cal2.setTime(date2);
cal2.add(Calendar.HOUR_OF_DAY, 2);
SimpleDateFormat printTimeFormat = new SimpleDateFormat("HH:mm a");
System.out.println(printTimeFormat.format(cal2.getTime()));
tl;dr
LocalDateTime.parse(
"2018-01-23 01:23:45".replace( " " , "T" )
).plusHours( 2 )
java.time
The modern approach uses the java.time classes added to Java 8, Java 9, and later.
user enters in the format YYYY-MM-DD HH:MM:SS
Parse that input string into a date-time object. Your format is close to complying with standard ISO 8601 format, used by default in the java.time classes for parsing/generating strings. To fully comply, replace the SPACE in the middle with a T.
String input = "2018-01-23 01:23:45".replace( " " , "T" ) ; // Yields: 2018-01-23T01:23:45
Parse as a LocalDateTime given that your input lacks any indicator of time zone or offset-from-UTC.
LocalDateTime ldt = LocalDateTime.parse( input ) ;
add two hours
The java.time classes can do the math for you.
LocalDateTime twoHoursLater = ldt.plusHours( 2 ) ;
Time Zone
Be aware that a LocalDateTime does not represent a moment, a point on the timeline. Without the context of a time zone or offset-from-UTC, it has no real meaning. The “Local” part of the name means any locality or no locality, rather than any one particular locality. Just saying "noon on Jan 21st" could mean noon in Auckland, New Zealand which happens several hours earlier than noon in Paris France.
To define an actual moment, you must specify a zone or offset.
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ; // Define an actual moment, a point on the timeline by giving a context with time zone.
If you know the intended time zone for certain, apply it before adding the two hours. The LocalDateTime class assumes simple generic 24-hour days when doing the math. But in various time zones on various dates, days may be 23 or 25 hours long, or may be other lengths. So, for correct results in a zoned context, add the hours to your ZonedDateTime rather than LocalDateTime.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.