SimpleDateFormat add some minutes - java

Im trying parse a date from a JSONObject
"timcre_not":"2013-12-11 21:25:04.800842+01"
and I parse with
mDate = new SimpleDateFormat("y-M-d h:m:s.SSSSSSZZ",
Locale.ENGLISH).parse(json.getString("timcre_not"));
but the mDate value is:
Wed Dec 11 21:38:24 CET 2013
What is happening?

This should be the solution: Date object SimpleDateFormat not parsing timestamp string correctly in Java (Android) environment
SimpleDateFormat cannot take microseconds, only milliseconds.

The answer by treeno is correct.
Joda-Time
As an alternative, you can use the third-party open-source Joda-Time. Joda-Time is often used to supplant the java.util.Date & Calendar classes found in Java (and Android).
ISO 8601
The string you have is loosely in ISO 8601 format. Replace that SPACE with a LATIN CAPITAL LETTER T "T" character to get a strict ISO 8601 format.
Joda-Time's DateTime class accepts an ISO 8601 string directly to its constructor. One catch: As with java.util.Date, a DateTime tracks only to the millisecond not microsecond. But in Joda-Time, rather than throw an error, the DateTime merely truncates (ignores) the extra (beyond 3) decimal places.
Example Code
Here is some example code using Joda-Time 2.3 and Java 8.
String input = "2013-12-11 21:25:04.800842+01";
String string = input.replace( " ", "T" ); // Replace SPACE with "T" for strict ISO 8601 format.
DateTime dateTimeUtc = new DateTime( string, DateTimeZone.UTC );
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" );
DateTime dateTimeParis = new DateTime( string, timeZone );
Dump to console…
System.out.println( "dateTimeUtc: " + dateTimeUtc );
System.out.println( "dateTimeParis: " + dateTimeParis );
When run…
dateTimeUtc: 2013-12-11T20:25:04.800Z
dateTimeParis: 2013-12-11T21:25:04.800+01:00
Java 8
I tried using the new java.time.* classes in Java 8 to parse your string.
ZonedDateTime zonedDateTime = ZonedDateTime.parse( string );
Unfortunately, the parser did not tolerate the time zone offset being the shortened +01. I tried the longer +01:00 and it worked. This seems to be a flaw in the Java implementation, not your string. The shortened offset is allowed in ISO 8601. While both I and RFC 3339 (a near-profile of ISO 8601) prefer using the longer +01:00, the ISO standard doe allow it and so should the java.time.* classes. I filed Bug Id: 9009717 with Oracle.
Get Better Data
If possible, suggest to the source of your date that they use the more strict and common ISO 8601 format including:
Use the letter "T" in place of SPACE
Longer time zone offset, "+01:00" rather than "+01"

Related

java date format "2023-01-25 16:30:22.998" vs "2023-01-16T23:59:59.938Z" [duplicate]

This question already has answers here:
What is this date format? 2011-08-12T20:17:46.384Z
(11 answers)
Closed 24 days ago.
Any help or hint would be greatly appreciated. From the below code I get this date:2023-01-25 16:30:22.998. How can I get this date: "FrmDt": "2023-01-16T23:59:59.938Z". It has a "T" which I not sure what this mean?
java.util.Date tsFrom = new java.util.Date();
Calendar calFrom = Calendar.getInstance();
calFrom.setTime(tsFrom);
calFrom.add(Calendar.YEAR, -1);
tsFrom.setTime(calFrom.getTime().getTime()); // or
sqlTSFromDate = new Timestamp(calFrom.getTime().getTime());
System.out.println("From date:" + sqlTSFromDate);
tl;dr
OffsetDateTime
.now( ZoneOffset.UTC )
.minus( Period.ofYears( 1 ) )
.toString()
2022-01-27T02:02:36.985475Z
ISO 8601
Study the ISO 8601 standard formats for textually representing date-time values.
Avoid legacy classes
Never use the legacy classes Date, Calendar, Timestamp. They are terribly flawed, designed by people who did not understand date-time handling.
java.time
Instead, use the java.time classes defined in JSR 310.
Apparently you want one year prior to the the current moment as seen in UTC.
Capture the current moment in UTC.
OffsetDateTime oneYearAgoInUtc = OffsetDateTime.now( ZoneOffset.UTC );
now.toString(): 2023-01-27T02:02:36.985475Z
Go back a year, using calendar dates as seen in the offset of zero, in UTC. First define the amount of time to go back, using Period for a scale of years-months-days.
Period p = Period.ofYears( 1 );
Then subtract.
OffsetDateTime then = now.minus( p );
then.toString(): 2022-01-27T02:02:36.985475Z
See that code run at Ideone.com.
To generate text in standard ISO 8601, merely call toString. The java.time classes use ISO 8601 formats by default when generating/parsing text.
String output = then.toString() ; // By default, standard ISO 8601 format.
2022-01-27T02:02:36.985475Z
The T separates the year-month-day portion from the hour-minute-second portion.
The Z indicates an offset from UTC of zero hours-minutes-seconds.
As several comments said, this is an ISO 8601 date.
In java, you can parse or write using SimpleDateFormat.
With the Z at the end, makle sure to use UTC/Zulu time.
Amending your code:
public static String ISO_8601 = "yyyyMMdd'T'HHmmss'Z'";
...
SimpleDateFormat dateFormat = new SimpleDateFormat(ISO_8601);
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
sqlTSFromDate = dateFormat.format(tsFrom)

Java SimpleDateFormat time wierdness

I am trying to parse a date string into a java.util.Date using java.text.SimpleDateFormat; however, the resulting formatted date is wrong.
Here is a test case showing the issue:
#Test
public void testSimpleDateFormat() throws Exception {
String dateString = "2016-03-03 11:50:39.5960000";
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSSS");
Date date = format.parse(dateString);
assertEquals(dateString, format.format(date));
}
This results in the following failure:
org.junit.ComparisonFailure:
Expected :2016-03-03 11:50:39.5960000
Actual :2016-03-03 13:29:59.0000000
The date is correct, but the hours, minutes, seconds, and milliseconds are all wrong. Why is java.text.SimpleDateFormat messing up the time on my date?
Your pattern says that 5960000 is a number of milliseconds. That represents 5960 seconds, so approximately 1 hour and 39 minutes, which explains the difference between the date you obtain and the initial one.
java.time
You are using old classes that have proven to be confusing, troublesome, and poorly designed. Avoid them. They have been supplanted by the java.time framework built into Java 8 and later.
The java.time classes use resolution of nanoseconds, for up to nine digits of a decimal fraction of second. More than enough for your six digits (microseconds).
Your input string is close to the standard ISO 8601 format. That format is used by default in java.time for parsing/generating string representations of date-time values. So, need to specify parsing pattern.
Morph your input string into standard format. Replace the SPACE in the middle with a T.
String input = "2016-03-03 11:50:39.5960000";
String inputStandardized = input.replace( " " , "T" );
Parse that string into a date-time object.
LocalDateTime ldt = LocalDateTime.parse( inputStandardized );
To get an actual moment on the timeline, assign an offset or time zone intended for this input.
If in UTC, create a OffsetDateTime.
OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC );
If a specific time was intended, create a ZonedDateTime.
ZonedDateTime zdt = ldt.atZone( ZoneId.of( "America/Montreal" ) ) ;
Before Java 8
If you do not yet have Java 8 technology available, consider adding either the backport of java.time or Joda-Time (the inspiration for java.time). For Android, there is a specific wrapper of the backport, ThreeTenABP.

Gson deserialize Java.util.Date with timezone

I deserialize a json string with date:
"created_at": "2015-12-24T17:41:54+01:00",
I set date format for gsonBuilder:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").create();
The deserialization works without crash; unfortunately when I print the result it's not correct:
SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd'T'HH:mm:ssZ");
String str = ft.format(response.createdAt);
The result is:
2015-12-24T11:41:54-0500
instead of:
2015-12-24T17:41:54+01:00
You haven't set the timezone only added a Z to the end of the date/time, so it will look like a GMT date/time but this doesn't change the value.
Set the timezone to GMT and it will be correct.
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
java.time
The accepted Answer is correct. But outdated. The java.text.SimpleDateFormat and java.util.Date classes have been outmoded by the java.time framework added to Java 8 and later. Much easier to use and more sensible.
ISO 8601
The format of your input string complies with the ISO 8601 standard. The java.time classes use ISO 8601 as their default formats when parsing/generating string representations of date-time values.
String input = "2015-12-24T17:41:54+01:00";
Offset-From-UTC
That input string includes an offset-from-UTC of +01:00, meaning an hour ahead of UTC.
ZonedDateTime zdt = ZonedDateTime.parse ( input );
ZoneId z = zdt.getZone ();
Offset versus Time Zone
But that offset is not a time zone. A time zone is an offset plus rules for handling anomaly adjustments such as Daylight Saving Time (DST). So you may well want to assign a specific time zone you have in mind as being intended by that string. Perhaps you intended Amsterdam time.
We can apply a time zone to get another ZonedDateTime object. This pattern of creating a new object based on an old object’s values rather than changing the old values directly is known as immutable objects.
A ZoneId is a full time zone in java.time. Its subclass ZoneOffset is for simple offset-from-UTC values without the adjustment rules.
ZoneId zoneIdAmsterdam = ZoneId.of ( "Europe/Amsterdam" );
ZonedDateTime zdtAmsterdam = zdt.withZoneSameInstant ( zoneIdAmsterdam );
toString
When you call toString such as in a System.out.println, java.time classes generate a String representation of the date-time value using ISO 8601 format.
Note that java.time extends ISO 8601 by appending the name of an assigned time zone in square brackets in addition to the offset-from-UTC number. For example, [Europe/Amsterdam].
System.out.println ( "zdt: " + zdt + " at zoneId z: " + z + " adjusted to zoneIdAmsterdam: " + zoneIdAmsterdam + " is zdtAmsterdam: " + zdtAmsterdam );
zdt: 2015-12-24T17:41:54+01:00 at zoneId z: +01:00 adjusted to zoneIdAmsterdam: Europe/Amsterdam is zdtAmsterdam: 2015-12-24T17:41:54+01:00[Europe/Amsterdam]
Instant
Generally in our business logic and data storage we work strictly in UTC, applying a time zone only for presentation to the user. For this purpose, pass and store an instance of the Instant class. This class represents a moment on the timeline in UTC.
Instant instant = zdt.toInstant();

What is the easiest way to get a formatted string from a calendar object which respects timezone?

When I search online about "how to convert a Calendar to a String", all the results I find suggest to first convert to a Date and then convert the Date to a String.
The problem is that a Date is only a representation of the number of milliseconds since the epoch - it does not respect timezone. Calendar is more advanced in this way.
Of course, I could call the individual Calendar.get methods to create my own formatted string, but surely there must be an easier way?
To illustrate, I wrote this code:
long currentTime = Calendar.getInstance().getTimeInMillis();
Calendar calendar = new GregorianCalendar();
calendar.setTimeZone(TimeZone.getTimeZone("Europe/Madrid"));
calendar.setTimeInMillis(currentTime);
System.out.println(calendar.getTime().toString());
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(calendar.getTime()));
System.out.println(calendar.get(Calendar.HOUR_OF_DAY));
While running this code from a machine based in London (UTC+0) at 8:02pm, I got the following results:
Wed Nov 18 20:02:26 UTC 2015
2015-11-18 20:02:26
21
The last line shows the real hour according to the calendar's timezone (Madrid which is UTC+1). It is 9:02pm in Madrid, but obviously both the native Date.toString as well as the DateFormat.format methods ignore the timezone because the timezone information is erased when calling Calendar.getTime (similarly Calendar.getTimeInMillis).
Given this, what is the best way to get a formatted string from a Calendar which respects timezone?
Set the timezone on the SimpleDateFormat object and then use z ..
sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
sdf.setTimeZone(TimeZone.getTimeZone("Europe/Madrid"));
System.out.println(sdf.format(calendar.getTime());
See here for details on how to handle timezones in Java.
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("Europe/Madrid"));
Calendar cal = Calendar.getInstance();
System.out.println(simpleDateFormat.format(cal.getTime()));
java.time
While the other Answers appear to be correct, a better approach is to avoid using java.util.Date/.Calendar entirely.
Those old date-time classes have been superseded by the java.time framework built into Java 8 and later. The new classes are inspired by the highly successful Joda-Time framework, intended as its successor, similar in concept but re-architected. Defined by JSR 310. Extended by the ThreeTen-Extra project. See the Tutorial.
Instant
An Instant represents a moment on the timeline in UTC.
Instant instant = Instant.now ( ); // Current moment in UTC.
For a given Calendar object, convert to an Instant using the method toInstant added in Java 8.
Instant instant = myCalendar.toInstant();
ZonedDateTime
You can assign a time zone (ZoneId) to an Instant to get a ZonedDateTime.
ZoneId zoneId = ZoneId.of ( "Europe/Madrid" );
ZonedDateTime zdt = ZonedDateTime.ofInstant ( instant, zoneId );
String Representation of Date-Time Value
Dump to console.
System.out.println ( "instant: " + instant + " adjusted into zone: " + zoneId + " is zdt: " + zdt );
The java.time classes use ISO 8601 standard formatting by default when parsing/generating String representations of date-time values. By default the ISO 8601 style is extended by appending the name of the time zone in addition to the usual offset-from-UTC.
instant: 2015-11-18T22:23:46.764Z adjusted into zone: Europe/Madrid is zdt: 2015-11-18T23:23:46.764+01:00[Europe/Madrid]
If you want the ISO 8601 style but without the T, either call .replace( "T" , "" ) on the resulting String object or define your own formatter.
The java.time.format package can do the work of determining a localized format appropriate to a particular Locale.
Locale locale = Locale.forLanguageTag ( "es-ES" );
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime ( FormatStyle.FULL );
String output = zdt.format ( formatter.withLocale ( locale ) );
miércoles 18 de noviembre de 2015 23H38' CET
You can use String.format() to avoid timezone problems
http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html
This example gives a result in the format: "yyyy-MM-dd HH:mm:ss"
Calendar c = Calendar.getInstance();
String s = String.format("%1$tY-%1$tm-%1$td:%1$tM:%1$tS", c);
System.out.println(s);
Output:
2015-11-20:44:55

Parsing date in from string in java

Hi so I do understand there are many threads out here regarding this and ive been through many of them I'm not able to grasp the whole date format thing so here I am seeking your help :)
I've got a json object giving me this date "2014-01-10T02:01:42.657Z" and I have no idea what sort of format that is. I do know its a datetime from mssql database and I wish to parse this in java for which I'm using this code.
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date result = null;
try {
result = df.parse(last_active);
} catch (ParseException e) {
Log.i("Date Parser problem (Friend.java): ", e.toString());
e.printStackTrace();
}
Log.i("Date: ", result.toString());
I do understand that the "yyyy-MM-dd HH:mm:ss" is the wrong format to parse this date with but I am not able to find the right type of format string to format the following date.
"2014-01-10T02:01:42.657Z"
I appreciate your help :)
Thank you
This is simply a standard ISO-formatted date. The T in the middle is simply a separator, and the Z at the end means "UTC".
To parse it, simply use yyyy-MM-dd'T'HH:mm:ss.SSSX as the pattern.
Try this
SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
ISO 8601
That string is in standard format, as defined by ISO 8601. In various protocols, this format is gradually replacing the silly formats of yesteryear such as Sun, 06 Nov 1994 08:49:37 GMT.
Avoid java.util.Date/Calendar
The bundled classes java.util.Date and .Calendar are notoriously troublesome. Avoid them. With the arrival of the java.time package in Java 8, they are practically deprecated. If you cannot go to Java 8, use Joda-Time (which inspired java.time).
Joda-Time
The Joda-Time library (third-party, open-source, free-of-cost) uses ISO 8601 for its defaults. So the Joda-Time class DateTime automatically parses such strings.
DateTime dateTime = new DateTime( "2014-01-10T02:01:42.657Z" );
Dump to console…
System.out.println( "dateTime: " + dateTime );
When run…
dateTime: 2014-01-09T18:01:42.657-08:00
Time Zone
Notice Joda-Time applied my JVM’s default time zone thereby adjusting the time appropriately. If you wish to keep the DateTime object in UTC, pass a DateTimeZone object in that constructor.
DateTime dateTime = new DateTime( "2014-01-10T02:01:42.657Z", DateTimeZone.UTC );
When run…
dateTime: 2014-01-10T02:01:42.657Z
java.time
The java.time package also uses ISO 8601 for its defaults, and automatically parses such standard strings.
Instant instant = Instant.parse( "2014-01-10T02:01:42.657Z" );
Dump to console…
System.out.println( "instant: " + instant );
When run…
instant: 2014-01-10T02:01:42.657Z

Categories