I am trying to reformat a date string using sdf. SDF is decrementing the date by a day. Pointers would be helpful.
java version "1.8.0_31"
Input: ChangeDateStringFormat("10-Mar-2015");
Code:
public static String ChangeDateStringFormat (String Input) throws InterruptedException
{
System.out.print("Input Date inside ChangeDateStringFormat : " + Input );
SimpleDateFormat sdf = new SimpleDateFormat("MMM-dd-yyyy");
sdf.setTimeZone(TimeZone.getTimeZone("MST"));
System.out.print(" || Output Date inside ChangeDateStringFormat : " + sdf.format(new Date(Input)) + "\n");
return sdf.format(new Date(Input));
}
Output Actual:
Input Date inside ChangeDateStringFormat : 10-Mar-2015 || Output Date inside ChangeDateStringFormat : Mar-09-2015
Output I was Expecting :
Input Date inside ChangeDateStringFormat : 10-Mar-2015 || Output Date inside ChangeDateStringFormat : Mar-10-2015
This is the problem:
new Date(Input)
You should not use that. Instead, construct a SimpleDateFormat to parse your input:
import java.text.*;
import java.util.*;
public class Test {
public static void main(String[] args) throws ParseException {
System.out.println(convertDateFormat("10-Mar-2015"));
}
public static String convertDateFormat(String input) throws ParseException {
TimeZone zone = TimeZone.getTimeZone("MST");
SimpleDateFormat inputFormat = new SimpleDateFormat("dd-MMM-yyyy", Locale.US);
inputFormat.setTimeZone(zone);
SimpleDateFormat outputFormat = new SimpleDateFormat("MMM-dd-yyyy", Locale.US);
outputFormat.setTimeZone(zone);
Date date = inputFormat.parse(input);
return outputFormat.format(date);
}
}
However:
If you're just parsing a date, you'd be better of specifying UTC as the time zone; you don't want to end up with problems due to time zones that switch DST at midnight
If you're going to run this code on Java 8 and nothing lower, I'd strongly recommend using java.time instead of Date, Calendar etc.
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.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
// Test
System.out.println(changeDateStringFormat("10-Mar-2015"));
}
static String changeDateStringFormat(String input) {
DateTimeFormatter dtfInput = DateTimeFormatter.ofPattern("d-MMM-u", Locale.ENGLISH);
DateTimeFormatter dtfOutput = DateTimeFormatter.ofPattern("MMM-dd-uuuu", Locale.ENGLISH);
LocalDate date = LocalDate.parse(input, dtfInput);
return date.format(dtfOutput);
}
}
Output:
Mar-10-2015
ONLINE DEMO
Note: Never use SimpleDateFormat or DateTimeFormatter without a Locale.
Learn more about the modern Date-Time API from Trail: Date Time.
Side Note: Always follow Java naming conventions e.g. the name of your function should be changeDateStringFormat instead of ChangeDateStringFormat and the parameter Input should be named as input.
* 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.
Related
I wan to convert the string d (date in UTC format) to String in UTC format with 'T' and increment 5 mins to time. Below is the code
public static void main (String args[]) throws ParseException
{
String d="2021-08-27 06:25:00.716241+00:00";
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSSXXX");
SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
Date actualDate = format.parse(d);
String a=format1.format(actualDate);
System.out.println(a);
}
I get output as 2021-08-27T12:06:56 but I need String 'a' as 2021-08-27T06:25:00 and then add 5 mins to it and make it 2021-08-27T06:30:00
Please help
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.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String d = "2021-08-27 06:25:00.716241+00:00";
DateTimeFormatter dtfInput = DateTimeFormatter.ofPattern("u-M-d H:m:s.SSSSSSXXX", Locale.ENGLISH);
OffsetDateTime odt = OffsetDateTime.parse(d, dtfInput);
DateTimeFormatter dtfOutput = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss", Locale.ENGLISH);
String str = odt.format(dtfOutput);
System.out.println(str);
// Add 5 minutes to it
odt = odt.plusMinutes(5);
str = odt.format(dtfOutput);
System.out.println(str);
}
}
Output:
2021-08-27T06:25:00
2021-08-27T06:30:00
ONLINE DEMO
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 want to convert a String (with reserved characters) to Date in Java
I have a string with some reserved characters in it. I am getting it from some source. Also I get the format of it from the same source. I tried to convert that string to a date but I was unable to.
The date I get:
{ts '2021-03-24 12:52:38.933'}
The format I get:
'{ts' ''yyyy-MM-dd HH:mm:ss{.SSS}[Z]'''}'
I tried with the sample code snippet but since {} are reserved characters and also ts is an invalid character for parsing, I am unable to parse it. Please help with how I can solve this.
Obviously I can do some string manipulation and convert it to a format I want but I don't want to do that.
String dateInString = "{ts '2021-03-24 12:52:38.933'}";
SimpleDateFormat sdf = new SimpleDateFormat("{ts' ''yyyy-MM-dd HH:mm:ss{.SSS}[Z]'''}", Locale.ENGLISH);
try {
Date date = sdf.parse(dateInString);
System.out.println(date);
} catch (ParseException e) {
e.printStackTrace();
}
You need to escape ' with another '.
Demo:
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 dateInString = "{ts '2021-03-24 12:52:38.933'}";
SimpleDateFormat parser = new SimpleDateFormat("'{ts '''yyyy-MM-dd HH:mm:ss.SSS'''}'", Locale.ENGLISH);
Date date = parser.parse(dateInString);
System.out.println(date);
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
System.out.println(formatter.format(date));
}
}
Output:
Wed Mar 24 12:52:38 GMT 2021
2021-03-24T12:52:38.933
ONLINE DEMO
Note that 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.text.ParseException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) throws ParseException {
String dateInString = "{ts '2021-03-24 12:52:38.933'}";
DateTimeFormatter parser = DateTimeFormatter.ofPattern("'{ts '''yyyy-MM-dd HH:mm:ss.SSS'''}'", Locale.ENGLISH);
LocalDateTime ldt = LocalDateTime.parse(dateInString, parser);
System.out.println(ldt);
}
}
Output:
2021-03-24T12:52:38.933
ONLINE DEMO
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.
This question already has answers here:
display Java.util.Date in a specific format
(11 answers)
want current date and time in "dd/MM/yyyy HH:mm:ss.SS" format
(11 answers)
convert java.util.Date to java.util.Date with different formating in JAVA [duplicate]
(1 answer)
SimpleDateFormat ignoring month when parsing
(4 answers)
Closed 2 years ago.
Tried converting string of yyyy-mm-dd, example 2013-12-30, to date object using SimpleDateFormat.parse("yyyy-mm-dd").
Expected output of 2013-12-30, received output of Mon Dec 30 00:00:00 EST 2013 object.
Tried finding out why SimpleDateFormat is returning a different format, but overwhelmed when trying to look through the java api. Asking for clarifications on what is going on and what would be a better approach.
Note: Stuck using java.utl.Date.
...
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateArray = new Date[rowCount];
try {
for(int index = 0; index < rowCount; index++){
dateArray[index] = simpleDateFormat.parse(fileArray[index][0]);
System.out.println(dateArray[index].toString());
}
} catch(ParseException err){
System.out.println("ERR: Data parse exception. Format is not correct.");
err.printStackTrace();
}
The pattern, mm stands for minute, not month. For month, you need to use MM.
Demo:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Main {
public static void main(String[] args) throws ParseException {
String strDate = "2013-12-30";
SimpleDateFormat sdfISO8601 = new SimpleDateFormat("yyyy-MM-dd");
Date date = sdfISO8601.parse(strDate);
System.out.println(date);
String strDateISO8601 = sdfISO8601.format(date);
System.out.println(strDateISO8601);
// Some other format
String strSomeOtherFormat = new SimpleDateFormat("EEEE MMM dd yyyy").format(date);
System.out.println(strSomeOtherFormat);
}
}
I also recommend you check Convert UTC String to UTC Date.
Note that the date-time API of java.util and their formatting API, SimpleDateFormat are outdated and error-prone. I suggest you should stop using them completely and switch to the modern date-time API.
Using the modern date-time API:
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
String strDate = "2013-12-30";
LocalDate date = LocalDate.parse(strDate);
System.out.println(date);
String strDate8601 = date.toString();
System.out.println(strDate8601);
// Custom format
String customFormat = DateTimeFormatter.ofPattern("EEEE MMM dd uuuu").format(date);
System.out.println(customFormat);
}
}
Your date string is already in ISO 8601 format for date and therefore do not need to use any formatter to parse it when you use the modern date-time API.
Learn more about the modern date-time API at Trail: Date Time.
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 which can contain a date(yyyy-MM-dd) or date and time (yyyy-MM-dd HH:mm:ss) in respective formats.
I want to know which strings contains only date.
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
System.out.println(dateFormat.parse("2015-02-02"));
System.out.println(dateFormat.parse("2015-02-02 23:23:23"));
In above code, both the strings are parsed successfully, whereas the format is same for only first.
I would use the overload of parse which takes a ParsePosition - you can then check the position afterwards:
import java.util.*;
import java.text.*;
public class Test {
public static void main(String[] args) throws Exception {
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateFormat.setLenient(false);
System.out.println(parseFully(dateFormat, "2015-02-02"));
System.out.println(parseFully(dateFormat, "2015-02-02 23:23:23"));
}
private static Date parseFully(DateFormat format, String text)
throws ParseException {
ParsePosition position = new ParsePosition(0);
Date date = format.parse(text, position);
if (position.getIndex() == text.length()) {
return date;
}
if (date == null) {
throw new ParseException("Date could not be parsed: " + text,
position.getErrorIndex());
}
throw new ParseException("Date was parsed incompletely: " + text,
position.getIndex());
}
}
public static void main(String[] args) {
String dateOnly = "2015-02-02";
String dateAndTimeOnly = "2015-02-02 23:23:23";
System.out.println("Date Only = " + validateDateFormat(dateOnly));
System.out.println("Date And time Only = " + validateDateFormat(dateAndTimeOnly));
}
public static boolean validateDateFormat(String input) {
return input.matches("([0-9]{4})-([0-9]{2})-([0-9]{2})");
}
output
Date Only = true
Date And time Only = false
Regex is self explanatory - Input will be separated by -, ist part([0-9]{4}) can contain 4 digit , 2nd part can contain 2 digit [0-9]{2}, so as 3rd.
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:
Let's first try to do it the way you have done:
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String[] arr = { "2015-02-02", "2015-02-02 23:23:23" };
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd", Locale.ENGLISH);
for (String s : arr) {
System.out.println("Attempting to parse '" + s + "':");
LocalDate date = LocalDate.parse(s, dtf);
System.out.println("Parsed successfully: " + date);
}
}
}
Output:
Attempting to parse '2015-02-02':
Parsed successfully: 2015-02-02
Attempting to parse '2015-02-02 23:23:23':
Exception in thread "main" java.time.format.DateTimeParseException: Text '2015-02-02 23:23:23' could not be parsed, unparsed text found at index 10
As you can see, the java.time API correctly throws an exception informing you about the problem. SimpleDateFormat, on the other hand, parses the input string silently which has caused the problem that you have posted.
Thus, with the modern date-time API, you have two easy options:
Simply catch the exception and say that the second input (i.e. 2015-02-02 23:23:23) is not a date string as per the specified date pattern.
Use the function, DateTimeFormatter#parse(CharSequence, ParsePosition) with the ParsePosition index set to 0.
Given below is a demo of the second option:
import java.text.ParsePosition;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String[] arr = { "2015-02-02", "2015-02-02 23:23:23" };
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd", Locale.ENGLISH);
for (String s : arr) {
ParsePosition pp = new ParsePosition(0);
LocalDate.from(dtf.parse(s, pp));
if (pp.getIndex() < s.length()) {
System.out.println("'" + s + "' is not a date string as per the specified date pattern.");
}
}
}
}
Output:
'2015-02-02 23:23:23' is not a date string as per the specified date pattern.
ONLINE DEMO
Note: 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.
Once the desired format is reached , SimpleDateFormat doesnt format the rest of String . It is the reason why your second string is parsed.
This post SimpleDateFormat parse(string str) doesn't throw an exception when str = 2011/12/12aaaaaaaaa? may help you .
Also check the DateFormat#parse method in java docs
I will be giving input date time for a timezone and the timezone for the input date time and we want the relevant DateTime in the expected timezone.
And here is my method.
convertToTimezone("03/08/2010 20:19:00 PM","Asia/Shanghai","US/Central");
The above time is the time in Asia/Shanghai. We would like to know what is the corresponding time in US/Central.
It's working fine but I am getting a 1-hour difference from the actual time.
Can I know where I am going wrong?
Here is the code:
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
public class DateUtil {
private static String format_date = "MM/dd/yyyy HH:mm:ss a";
public static void main(String a[]) {
try {
String sourceTimezone = "Asia/Shanghai";
String destTimezone = "US/Central";
String outputExpectedTimezone = convertToTimezone("03/08/2010 20:19:00 PM", sourceTimezone, destTimezone);
System.out.println("outputExpectedTimezone :" + outputExpectedTimezone);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static String convertToTimezone(String inputDate, String inputDateTimezone, String destinationDateTimezone)
throws Exception {
String outputDate = null;
SimpleDateFormat format = new SimpleDateFormat(format_date);
format.setTimeZone(TimeZone.getTimeZone(inputDateTimezone));
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone(inputDateTimezone));
calendar.setTime(format.parse(inputDate));
calendar.add(Calendar.MILLISECOND, -(calendar.getTimeZone().getRawOffset()));
calendar.add(Calendar.MILLISECOND, -calendar.getTimeZone().getDSTSavings());
calendar.add(Calendar.MILLISECOND, TimeZone.getTimeZone(destinationDateTimezone).getRawOffset());
outputDate = format.format(calendar.getTime());
return outputDate;
}
}
You shouldn't be adding anything to the calendar - that represents a specific instant in time. In fact, you don't need a calendar at all.
Instead, have two different formats, one for each time zone:
public static String convertToTimezone(String inputDate,
String inputDateTimezone,
String destinationDateTimezone)
throws Exception
{
SimpleDateFormat parser = new SimpleDateFormat(format_date);
parser.setTimeZone(TimeZone.getTimeZone(inputDateTimezone));
Date date = parser.parse(inputDate);
SimpleDateFormat formatter = new SimpleDateFormat(format_date);
formatter.setTimeZone(TimeZone.getTimeZone(outputDateTimezone));
return formatter.format(date);
}
As an aside, I'd thoroughly recommend using Joda Time instead of the built-in date/time API.
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:
Since your input Date-Time does not have timezone information, parse it into a LocalDateTime
Attach the timezone of the input Date-Time with it to get a ZonedDateTime
Use the ZonedDateTime#withZoneSameInstant to convert this ZonedDateTime to the target ZonedDateTime
Return the formatted target 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) {
// Tests
System.out.println(convertToTimezone("03/08/2010 20:19:00 PM", "Asia/Shanghai", "US/Central"));
System.out.println(convertToTimezone("03/08/2010 20:19:00 PM", "Asia/Shanghai", "America/Mexico_City"));
}
static String convertToTimezone(String inputDate, String inputDateTimezone, String destinationDateTimezone) {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("MM/dd/uuuu HH:mm:ss a", Locale.ENGLISH);
LocalDateTime ldt = LocalDateTime.parse(inputDate, dtf);
ZonedDateTime zdtInput = ldt.atZone(ZoneId.of(inputDateTimezone));
ZonedDateTime zdtDestination = zdtInput.withZoneSameInstant(ZoneId.of(destinationDateTimezone));
return zdtDestination.format(dtf);
}
}
Output:
03/08/2010 06:19:00 AM
03/08/2010 06:19:00 AM
ONLINE DEMO
Note: Avoid using the deprecated ID, US/Central. Use the standard ID, America/Mexico_City where Mexico City is the largest city in this timezone.
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.