I need to communicate with one application that is not implementing the full ISO 8601 and only accept the format +HH:mm for time zone offset.
Android seems to only generate the format +HHmm (no ':' character in between hours and minutes) with the 'z' in SampleDateFormat.
Code example:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
String str = String.format(Locale.US, "%s", sdf.format(new Date(0)));
generates: 1970-01-01T00:00+0000
and I would like to generate: 1970-01-01T00:00+00:00
Is there any simple way of producing the desirable output without writing the code to manipulate the string?
Thanks,
Luis
I think the easiest way is to manipulate a string.
a) SimpleDateFormat doesn't support what you need.
b) The method appendNumericTimeZone in SimpleDateFormat class is private. So, you can't override it.
2) You can create your own formater (implement java.text.DataFormat). However, it will be way more hassle than string manipulation.
BTW. Interesting thing which I found while looking into SimpleDateFormat source code. There is some code which generates almost what you need (it adds to the end "GMT+XX:XX"). However, this code will be only called, if you specified "Z" in the format and system can't find a timezone name for current timezone.
Related
I am trying to check if the date has passed more than one day or not.
And I got these errosr while it parses the string.
java.lang.IllegalArgumentException: Pattern ends with an incomplete string literal: uuuu-MM-dd'T'HH:mm:ss'Z
org.threeten.bp.format.DateTimeParseException: Text '2020-04-04T07:05:57+00:00' could not be parsed, unparsed text found at index 19
My data example is here:
val lastDate = "2020-04-04T07:05:57+00:00"
val serverFormat = "uuuu-MM-dd'T'HH:mm:ss'Z"
val serverFormatter =
DateTimeFormatter
.ofPattern(serverFormat)
val serverDateTime =
LocalDateTime
.parse(
lastDate,
serverFormatter
)
.atZone(ZoneId.of("GMT"))
val clientDateTime =
serverDateTime
.withZoneSameInstant(ZoneId.systemDefault())
val timeDiff =
ChronoUnit.DAYS.between(
serverDateTime,
clientDateTime
I've tried with these:
uuuu-MM-dd\'T\'HH:mm:ss\'Z
yyyy-MM-dd\'T\'HH:mm:ss\'Z
uuuu-MM-dd\'T\'HH:mm:ss
uuuu-MM-dd'T'HH:mm:ss'Z
yyyy-MM-dd'T'HH:mm:ss'Z
uuuu-MM-dd'T'hh:mm:ss'Z
yyyy-MM-dd'T'hh:mm:ss'Z
yyyy-MM-dd HH:mm:ss
yyyy-MM-dd HH:mm:ssZ
yyyy-MM-dd'T'HH:mm:ss
yyyy-MM-dd'T'HH:mm:ssZ
yyyy-MM-dd'T'HH:mm:ss
And none of them worked... What is the correct way?
You don’t need any explicit formatter. In Java (because it’s what I can write):
String lastDate = "2020-04-04T07:05:57+00:00";
OffsetDateTime serverDateTime = OffsetDateTime.parse(lastDate);
ZonedDateTime clientDateTime
= serverDateTime.atZoneSameInstant(ZoneId.systemDefault());
System.out.println("serverDateTime: " + serverDateTime);
System.out.println("clientDateTime: " + clientDateTime);
Output in my time zone:
serverDateTime: 2020-04-04T07:05:57Z
clientDateTime: 2020-04-04T09:05:57+02:00[Europe/Copenhagen]
The format of the string from your server is ISO 8601. The classes of java.time parse the most common ISO 8601 variants as their default, that is, without any formatter being specified.
Since the string from your server has a UTC offset, +00:00, and no time zone, like Asia/Seoul, OffsetDateTime is the best and most correct time to use for it. On the other hand, the client time has got time zone, so ZonedDateTime is fine here.
Since server and client time denote the same time, the difference will always be zero:
Duration difference = Duration.between(serverDateTime, clientDateTime);
System.out.println(difference);
PT0S
Read as a period of time of 0 seconds (this too is ISO 8601 format).
If you want to know the difference between the current time and the server time, use now():
Duration difference = Duration.between(serverDateTime, OffsetDateTime.now());
System.out.println(difference);
What went wrong in your code?
First, the UTC offset in your string is +00:00. Neither one format pattern letter Z nor a literal Z will match this. So don’t try that. Second, never give Z as a literal enclosed in single quotes in your format pattern string. When a Z appears as an offset, which is common, you need to parse it as an offset, not as a literal. Third, literal text in a format pattern string needs to have a single quote before and a single quote after it. You are doing it correctly for the T in the middle. If you didn’t mean Z to be a literal, don’t put a single quote before it. If you did mean it to be a literal — as I said, just don’t.
Links
Wikipedia article: ISO 8601
Documentation of the one-arg OffsetDateTime.parse()
So time formatting and adjusting has always been my biggest nemesis in programing and I'm having some issues in Android/Java that I can't figure out. I get a timestamp from a server that is formatted in UTC (here's an example 2016-06-17T18:30:00-07:00. Now this time needs to get formatted to the users local time (so for a user in PST it should show as 11:30AM) but so far whatever I try I either get 1AM or 6:30PM (so I know I'm doing something wrong I just don't know what). Here's what I've been trying to do
public static DateTime convertISOStringToDate(String inputString) {
//setup the ISO Date Formatter with GMT/UTC format
DateTimeFormatter formatter = ISODateTimeFormat.dateTimeParser()
.withLocale(Locale.US)
.withZone(DateTimeZone.forOffsetHours(0));
DateTime dateTime = formatter.parseDateTime(inputString);
//now convert the datetime object to a local date time object
DateTimeFormatter localFormatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")
.withZone(DateTimeZone.getDefault());
String localString = localFormatter.print(dateTime);
DateTime localDateTime = localFormatter.parseDateTime(localString);
return localDateTime;
So at this point I'm getting 1:30AM, so I know I'm messing it up somewhere in the conversion process but I can't figure it out. I've been trying to google around but so far haven't found much that use the ISODateTimeFormat parser so they don't work either when I try them.
You seem to have a basic mis-understanding of how dates are represented.
A date (in almost every known programming language / library) is represented internally as an offset from a specific 'origin time', known as the 'Epoch'.
In java.util.Date as well as joda dates, the internal representation is the number of milliseconds since midnight, Jan 1, 1980, UTC.
As such, a date does not have a timezone. You only introduce a timezone when you format a date (turn it into a String representation of the date).
You have made the common mistake of parsing a String into a date object, serializing (printing) it back out with a different timezone than the the original string indicated, and then parsing back into a date again, expecting something to have changed. If you do that correctly, you will get back exactly the same date that you started with.
In your case, the "localString" that you get shows the correct time in the local timezone. I'm in EDT, which is UTC-4:00, and I correctly get 2016-06-17 21:30:00 as the result.
As I said, parsing that back into a DateTime, and then looking at it is useless, because:
You'll get the same DateTime back that you started with
Your IDE (or whatever you're using to inspect the DateTime) probably isn't showing what you expect.
You should re-evaluate what you're doing here, and whether you really need to "convert" the DateTime, or to just parse it, and really understand how date formatting works with respect to timezones.
I'm writing unit tests for Android code using the Robolectric gradle test runner. The code I'm testing happens to be hitting date formatting methods that use the following format:
yyyy-MM-dd'T'HH:mm:ss.SSSZ
We store Unix Time milliseconds as strings in that format, and just before sending it through the formatter to convert it back into a millisecond offset, we replace any instances of "Z" in the string with "+00:00". the call ends up looking like this:
DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
format.setTimeZone(TimeZone.getTimeZone("UTC"));
format.parse(validDateString.replace("Z", "+00:00));
This operation works fine in production code, but attempting to write unit tests has revealed previously unseen ParseExceptions. I first assumed it was because of a formatting issue with the date string I was injecting, but ParseExceptions are being thrown on strings saved from a date successfully parsed in prod code.
What could possibly be causing this radical difference in behavior?
Things I've tried already:
-Checked date formatting
-This DateFormat is actually a global static variable. I'm aware that they're not thread-safe, but inlining all static references with new instances yields the same results.
UPDATE:
Partial stack trace
java.text.ParseException: Unparseable date: "2016-02-20T19:47:33.262+00:00"
at java.text.DateFormat.parse(DateFormat.java:357)
...nothing else useful
Additionally, I should mention that we use a complementary method that stores milliseconds as a String:
DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
Date date = new Date(unixTime);
String validDateString = format.format(date);
return validDateString.replace("+0000", "Z");
Note that we're replacing 4 0's without a colon, whereas the method that fails appends 00:00. That said, the not-quite-complementary operations work fine in production, but fail in unit tests.
Try setting your string for unit test directly:
String validDateString = "2016-02-20T19:47:33.262+0000"; // remove the colon
I had the same issue when running Robolectric. As per this issue on GitHub, replacing +00:00 with +0000 fixed the issue for me.
I m developing android application. I need to convert datetime into date. I want to convert '25-07-2013 11:44AM' (datetime) into '25-07-2013' (date).
I am trying this function to convert SELECT date('25-07-2013 11:44AM'), but it was not working.Please suggest some solution for this problem.
According to this page, it does not seem that am/pm times are supported in date SQLite function (this should be noted as h or K according to the date format specification of Java at least; also it is explicitly mentioned %H hour: 00-24). Maybe experiment if using 24 hour clock will not trigger the issue.
I am not sure if you are search for Java code or SQL code , but if it is Java code then solution could be this :
String date = "25-07-2014 11:44AM";
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
String newDate = dateFormat.format(dateFormat.parse(date));
System.out.println(newDate);
If in case your are looking for SQL code let me know I will share that as well.
I read some posts on formatting date on android, like this:
How do you format date and time in Android?
People suggest use android.text.format.DateFormat rather than java.text.DateFormat,
Also here, it mention a problem when converting date to string in android:
Android load timezone too long: Loaded time zone names for en_US
I am wondering what's the difference between android.text.format.DateFormat and java.text.DateFormat?
As far as I can tell, android.text.format.DateFormat has some of the functionality from java.text.DateFormat, some of the functionality from java.text.SimpleDateFormat, and some extra functionality of its own.
Most notably:
The java SimpleDateFormat allows construction of arbitrary non-localized formats.
The java DateFormat allows construction of three localized formats each for dates and times, via its factory methods.
The android DateFormat allows most of the above (arbitrary formats and a smaller number of localized formats), but also provides getBestDateTimePattern which picks a locale-appropriate format string that contains the elements specified with locale-appropriate ordering and punctuation.
So, if you need a localized date/time format other than the three provided by java's DateFormat class, the android DateFormat class is the solution.
Less importantly, but an additional convenience: the android DateFormat methods can take a Calendar or long milliseconds directly, instead of requiring a Date object. I always prefer working with Calendar or long over Date. Also, it properly respects the timezone of the Calendar object -- whereas getting a Date from a Calendar and passing that along to the formatter loses the timezone information. (Nothing you can't get around via java DateFormat's setCalendar method, but it's nice to not have to.)
Finally, and least importantly, some of the methods of the Android DateFormat don't actually construct a formatter, you just construct a format string. All of this class's methods are static. The methods do that construct a DateFormat actually construct a java DateFormat!
How about some self-help here? Compare the APIs, read the JavaDocs and see for yourself:
java.text.DateFormat
android.text.format.DateFormat