Joda ISODateTimeFormat not using timezone in String - java

I have a two part issue, or maybe its two different ways to solve this. I receive an ISO string like 2015-11-17T17:10:24-0800. The end goal is to display the string as 11/17/15 5:10 PM in some HTML generated by some Freemarker. The string I receive could be in any timezone, but I always need to display the string in its local timezone as shown above. Currently, our code was just taking the string and passing it into the template and coverting as such:
<#assign mydate = obj.mydate?datetime("yyyy-MM-dd'T'HH:mm:ssz")?string.short>
This is no longer good since I believe Freemarker is using the system's local timezone and now we are getting more than one timezone. I see there is an iso method in freemarker. So I try
<#assign order_date = order.order_date?iso("yyyy-MM-dd'T'HH:mm:ssz")>
but I keep getting error:
For "?iso" left-hand operand: Expected a date, but this evaluated to a string
Ok I need a date. Working with Joda, I try and create a datetime object by:
DateTime dateTime = ISODateTimeFormat.dateTimeNoMillis().parseDateTime("2015-11-17T17:10:24-0800");
But that appears to use my local timezone as well and shows 2015-11-17T20:10:24.000-05:00. I know I could do withZone(...) but I dont know the zone other than the -0800 or whatever zone is passed at the end of the string. So I'm at a loss of what to do now. Oh, and I cannot change the format of the string I receive.

DateTime dateTime = ISODateTimeFormat.dateTimeNoMillis().withOffsetParsed().parseDateTime("2015-11-17T17:10:24-0800");
This will create a DateTime with a fixed timezone offset of -08:00.

May require a little more work, but you could always use the DateTimeFormatterBuilder to create your own custom display for the Date Time. This way you could drop the TimeZone if you care to and render it for within that TimeZone or render locally.

Related

Date toString without timezone conversion for MessageFormat

I'm using ibm's MessageFormat library to localize an incoming date.
The task here is to run a few checks on the date before showing it to the end user. I get a ZonedDateTime object and I need to make sure that it doesn't fall in the weekend, which I do using the getDayOfWeek.
My problem happens when I try to convert my date to a string using MessageFormat. Since MessageFormat accepts only java.util.Date objects, I convert my ZonedDateTime -> Instant -> Date. Unfortunately, this method results in my "Monday" becoming a "Sunday," as shown below.
I noticed that this "loss" happens upon the Date conversion. This is because the Date.toString() object is being invoked by MessageFormat, and the former uses the JVM's default timezone (in my case, PST). As a result, my UTC gets implicitly converted to a PST and I lose a day.
Any ideas how to tackle this? Is there anything else that I can pass to MessageFormat? Is there a way to use Date but not get this undesired behavior? Is there another localization library I can use?
Internally, MessageFormat uses a DateFormat object but does not allow you to set its timezone. #Assylias linked a question where the answer tries to pull out the internal DateFormat, set its timezone, and then use the MessageFormat as usual, which resolves the issue.
However, I found that to be too wordy, particularly because you have to create a new MessageFormat everytime (as opposed to reusing the MessageFormat that you already set the timezone for).
What I opted for was to simply use SimpleDateFormat directly.
// I have a ZonedDateTime zonedDateTime that I want to print out.
final SimpleDateFormat dateFormat = new SimpleDateFormat("EEEE, MM dd", locale);
dateFormat.setTimeZone(TimeZone.getTimeZone(zonedDateTime.getZone()));
final String formattedDateString = dateFormat.format(Date.from(zonedDateTime.toInstant()));
I then use String.format to insert my formatted date into a larger string. Hope this helps.

java.time.format.DateTimeParseException: could not be parsed at index 0

I am trying to convert a String to timestamp.
my string contains time and time zone ('05:03:05.875+02:00') but I get the following error:
error
java.time.format.DateTimeParseException: Text '05:03:05.875+02:00'
could not be parsed at index 0
Code
String timewithZone= "05:03:05.875+02:00";
DateTimeFormatter formatter=DateTimeFormatter.ISO_OFFSET_DATE_TIME;
final ZonedDateTime a2=ZonedDateTime.parse(timewithZone,formatter);
String timewithZone = "05:03:05.875+02:00";
OffsetTime time = OffsetTime.parse(timewithZone);
System.out.println("Parsed into " + time);
This outputs
Parsed into 05:03:05.875+02:00
Your string contains a time and an offset, but no date. This conforms nicely, neither with an ISO_OFFSET_DATE_TIME nor a ZonedDateTime, but with an OffsetTime, a seldom used class that I think is there exactly because such a thing sometimes occurs in XML.
There is also an ISO_OFFSET_TIME formatter built in, but since this is the default format for OffsetTime we do not need to specify it.
It is failing because your string does not have the date related tokens. Check the example in the official documentation. In order to make it work you will need to add year/month/day data:
String timewithZone= "2018-07-3T05:03:05.875+02:00";
You cannot use the DateTimeFormatter.ISO_OFFSET_DATE_TIME because your date format does not adhere to that.
In fact, you don't even have a real date because there is no date component, only a time component.
You could define your own SimpleDateFormat instance with the format you're receiving, but you'll have to handle the fact that this data isn't really all that useful without date information. For example, that offset doesn't really tell us that much, because it might be in some region's Daylight Savings Time (DST) or not. And this heavily depends on on what actual DATE it is, not just what time.
You'll have to find out what the provider of this data even means with this, because right now you simply don't have enough information to really parse this into a proper date.
If this data just means a simple time stamp, used for for example saying "our worldwide office hours lunch time is at 12:30" then you could us the LocalTime class. That would be one of the few cases where a time string like this without a date is really useful. I have a sneaking suspicion this is not your scenario though.
A workaround may be
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss.SSSz");
String str = "05:03:05.875+02:00";
LocalTime time = LocalTime.parse(str, formatter);
System.out.println(time);
I tried the code in the format what you are getting,
Output :
05:03:05.875
Is this the one you are looking for?

Datetime Parsing - Unable to get back original value

DateTimeFormatter DATEFORMAT = ISODateTimeFormat.dateTimeNoMillis();
String testDate = "2013-10-26T04:23:14-08:00";
System.out.println(testDate);
System.out.println(DATEFORMAT.parseDateTime(testDate).toString(DATEFORMAT));
Output:
2013-10-26T04:23:14-08:00
2013-10-26T05:23:14-07:00
Why are outputs off by around an hour ? Is there any other parameter I need to specify for converting DateTime back to string ?
Any help is much appreciated.
I'm assuming this is using the joda-time library. As the comments above suggest, it's a TZ issue. You can easily convert any of the times into the TZ of your choice or UTC through a method call on the DateTime object. Something along the lines of:
dt.withZone(DateTimeZone.UTC);
You're getting different results since the default behavior is to print the DateTime in the system's current timezone.

In Android,how is a string or other variable type parsed?

I'm querying my database to display the row based on the date column. I've got the method to function correctly, but I'm having to change the format of my date values in the database. Previously, I had the dates as yyyyMd which would get 201252 for today for example. Then I parsed the date into a Long and passed it into my method
String sd = hiddenDate.getText().toString();
long aLong = Long.parseLong(sd);
dba.open();
String[] rScr = dba.getTodayMethod(aLong);
But I'm having to rewrite the date format into yyyy-M-y. Then the dashes in the date are breaking the "parseLong" I think. And it appears that just passing the sd variable into the getTodayMethod, like String[] rScr = dba.getTodayMethod(sd); doesn't work either. So what should I parse the String sd into to accomodate the dashes in the date? and how would that parse code be written?
Fundamentally, you're doing the wrong thing by trying to parse it as a long to start with. It's not the textual representation of a 64-bit integer - it's the textual representation of a date. So use types that are to do with date/time.
Personally I like using Joda Time, but if you're on Android that may be too big for you - in which case you'll have to use java.util.Date and java.util.Calendar, horrible though they are, and then use java.text.SimpleDateFormat for the parsing. (Don't forget to set the locale and time zone appropriately...)

Parsing the JXDatePicker in order to insert into Java DB Date field?

I'd like to insert the value derived from this JXDatePicker into a Date field in Java DB. How should I get ONLY date off this controller in a way that time is represented as dd/mm/yyyy and nothing else??!
You can get the Date from the JXDatePicker.getDate() and then use a SimpleDateFormat to format the date into the required format.
Try:
SimpleDateFormat formater = new SimpleDateFormat("dd/MM/yyyy");
formater.format(myDatePicker.getDate());
Notice that instead of the mm that you've used I used MM to represent the month. Please see the SimpleDateFormat javadoc for pattern letters you can use.
Follow-Up
I feel compelled to mention, for completeness, that it is generally a bad idea to put formatted strings representing dates into a database; what happens when you want to display it in another format, for instance, or do a simple comparison using SQL.
One way to store date/times is to use the timestamp that you get from Date.getTime(). Here's the Date class' getTime() javadoc:
Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT
represented by this Date object.
Storing this representation of a Date in your database makes it much simpler to create a Date object when you retrieve the timestamp:
Long myTimeStamp = getTimeStampFromResultSet();
Date date = new Date(myTimeStamp);
Or use the column in SQL to do a simple comparison:
SELECT * FROM MY_TABLE WHERE MY_DATE > ?
It also makes it somewhat portable so you can, for instance, send the timestamp to a thin client that is built using a different technology.
That being said, it is also in your best interest to use a date and time library like Joda Time instead of using the unreliable and inconvenient Java Date or Calendar classes.

Categories