How to get local time from a specific string adding hh:mm - java

I have this date in this format:
String date = "2018-12-08T07:50:00+01:00";
And I'd like to get the local time in this format (adding the hours over GMT) but I'm not able to do it
date = "2018-12-08 08:50:00";
Other example:
String date = "2018-12-08T07:50:00+04:00";
Result:
date = "2018-12-08 11:50:00";
Any help?

As Sun already said in another answer, you misunderstood: 2018-12-08T07:50:00+01:00 is the same point in time as 2018-12-08 06:50:00 in UTC (roughly the same as GMT), not 08:50. +01:00 means that the time comes from a place where the clocks are 1 hour ahead of UTC, so to get the UTC time 1 hour should be subtracted, not added.
DateTimeFormatter desiredFormatter = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
String date = "2018-12-08T07:50:00+01:00";
OffsetDateTime dateTime = OffsetDateTime.parse(date);
OffsetDateTime dateTimeInUtc = dateTime.withOffsetSameInstant(ZoneOffset.UTC);
date = dateTimeInUtc.format(desiredFormatter);
System.out.println(date);
Output from this snippet is:
2018-12-08 06:50:00
Using your other example, 2018-12-08T07:50:00+04:00, the output is
2018-12-08 03:50:00
I am taking advantage of the fact that your string is in ISO 8601 format. OffsetDateTime parses this format as its default, that is, we don’t need to specify the format in a DateTimeFormatter (as we do for your desired result format).
Link: Wikipedia article: ISO 8601

2018-12-08T07:50:00+01:00, the +01:00 in the end does not mean adding hh:mm, it means the datetime is already local date time, in GMT it is 2018-12-08T06:50:00.
You can use string.replaceAll to remove T and +01:00:
String input = "2018-12-08T07:50:00+01:00";
input = input.replaceAll("T", " ");
input = input.replaceAll("\\+.*", "");
System.out.println(input); // 2018-12-08 07:50:00
or parse and re-format it:
OffsetDateTime offsetDateTime = OffsetDateTime.parse("2018-12-08T07:50:00+01:00");
String time = offsetDateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME).replace("T", " ");
System.out.println(time); // 2018-12-08 07:50:00

Related

Issue with ISO 8601 in Android API level 23

I've issue in format of java for ISO 8601, I'm using this code
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
//yyyy-MM-dd'T'HH:mm:ss.shh:mm
Date date = Calendar.getInstance().getTime();
String cDate = format.format(date);
Log.d("Date","Date is " + cDate);
My result is:
Date is 2019-04-03T04:37:52+0000
if I'm using this format yyyy-MM-dd'T'HH:mm:ssZ. And the result is:
Date is 2019-04-03T04:49:33.3304:49
if I'm using this format yyyy-MM-dd'T'HH:mm:ss.shh:mm. I've been tried my solutions but not is giving me my desired solution.
My desired solution is 2008-09-15T15:53:00+05:00. I try Offset but it's not working for API level 23, It's only for API level 28.
Here is the format mask you should be using:
yyyy-MM-dd'T'HH:mm:ssXXX
From the documentation for SimpleDateFormat, we can see that X represents the ISO 8601 time zone, which shows the timezone in terms of hours shifted from GMT.
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
format.setTimeZone(TimeZone.getTimeZone("Africa/Cairo"));
Date date = Calendar.getInstance().getTime();
String cDate = format.format(date);
System.out.println("Date is " + cDate);
Date is 2019-04-03T06:41:30+02:00
Note that I needed to assign a time zone other than GMT, because GMT just returns Z for the time zone.
Tim was right but his given pattern works for java, Not for that java which is in android.
For Android java use this pattern
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZZZZZ");
Then out put will be
Date is 2019-04-03T08:29:27+00:00

joda time unexpected format

I'm trying to use Joda-Time library to convert a String date and time to Date but the result I get is not the expected.
From the server I get:
08/11/2017 12:30
10/11/2017 12:30
Joda converts it to:
2017-01-08T12:30:00.000+02:00
2017-01-10T12:30:00.000+02:00
DateTimeFormatter formatter = DateTimeFormat.forPattern("dd/mm/yyyy HH:mm:ss");
// add two :00 at the end for the seconds
startDate = startDate +":00";
DateTime start = formatter.parseDateTime(startDate);
System.out.println(start.toString());
endDate= endDate + ":00";
DateTime end = formatter.parseDateTime(endDate);
That's because you're using mm for the month, but the correct pattern is uppercase MM. Check the documentation for more details.
One more thing. If your input doesn't have the seconds (:00), you don't need to append it in the end of the input strings. You can simply create a pattern without it:
// "MM" for month, and don't use "ss" for seconds if input doesn't have it
DateTimeFormatter formatter = DateTimeFormat.forPattern("dd/MM/yyyy HH:mm");
// parse input (without ":00" for the seconds)
DateTime start = formatter.parseDateTime("08/11/2017 12:30");
System.out.println(start.toString());
The output will be:
2017-11-08T12:30:00.000-02:00
Notice that the offset (-02:00) is different from yours. That's because DateTime uses the default timezone if you don't specify one.

Unable to convert UTC to IST, it is still returning me UTC only

I am trying to convert UTC Date to IST. But to my surprise, after converting everything, it is still returning me UTC only. How is it possible?
INPUT:
StartDateTimeUtc='2017-09-15T14:00:00',
EndDateTimeUtc='2017-09-15T15:00:00'
Code:
public static final String DATE_FORMATE_CURRENT = "yyyy-MM-dd'T'HH:mm:ss";
Date meetingStartDate = new SimpleDateFormat(Constants.DATE_FORMATE_CURRENT, Locale.ENGLISH).parse(model.StartDateTimeUtc);
Date meetingEndDate = new SimpleDateFormat(Constants.DATE_FORMATE_CURRENT, Locale.ENGLISH).parse(model.EndDateTimeUtc);
//Convert Date to String
DateFormat df = new SimpleDateFormat(Constants.DATE_FORMATE_CURRENT);
String meetinStartDateString = df.format(meetingStartDate);
String meetingEndDateString = df.format(meetingEndDate);
//Convert String Date to IST
SimpleDateFormat dftwo = new SimpleDateFormat(Constants.DATE_FORMATE_CURRENT);
dftwo.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));
Date date = null;
Date datetwo = null;
try {
date = dftwo.parse(meetinStartDateString);
datetwo = dftwo.parse(meetingEndDateString);
} catch (ParseException e) {
e.printStackTrace();
}
dftwo.setTimeZone(TimeZone.getDefault());
String formattedStartDate = dftwo.format(date);
String formattedEndDate = dftwo.format(datetwo);
//Convert String Date back to Date format so that we can pass into Calendar code
Date meetingStartDateFinal = new SimpleDateFormat(Constants.DATE_FORMATE_CURRENT, Locale.ENGLISH).parse(formattedStartDate);
Date meetingEndDateFinal = new SimpleDateFormat(Constants.DATE_FORMATE_CURRENT, Locale.ENGLISH).parse(formattedEndDate);
OUTPUT again in UTC:
Start Date : Fri Sep 15 14:00:00 GMT+05:30 2017
End Date : Fri Sep 15 15:00:00 GMT+05:30 2017
A java.util.Date doesn't have any timezone information. It just contains one value: the number of milliseconds since unix epoch (1970-01-01T00:00Z, or January 1st 1907, at midnight in UTC).
This number of milliseconds is the same, everywhere in the world. What's is different is the corresponding date and time in each timezone. Example: right now, this millis value is 1505481835424, which corresponds, in UTC, to 2017-09-15T13:23:55.424Z. This same value corresponds to 10:23 AM in São Paulo, 18:53 in Kolkata, 14:23 in London and so on. The local date/time is different in each timezone, but the millis value is the same for everyone.
That's why you don't convert a Date itself: the millis value is the same, and there's no need to change it. What you can change is the representation of this date in different timezones.
SimpleDateFormat, by default, uses the JVM default timezone to parse dates. But if you know that the inputs are in a specific zone, you must set in the formatter. So, to parse your inputs, you must do:
String startDateTimeUtc = "2017-09-15T14:00:00";
String endDateTimeUtc = "2017-09-15T15:00:00";
SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ss");
// input is in UTC
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
// parse dates
Date meetingStartDate = sdf.parse(startDateTimeUtc);
Date meetingEndDate = sdf.parse(endDateTimeUtc);
The 2 Date objects above will correspond to 14:00 and 15:00 UTC (which is the same as 19:30 and 20:30 in Kolkata timezone).
But if you just print the Date objects directly (using System.out.println, logging, or even checking their values in a debugger), it'll implicity call the toString() method, which uses the JVM default timezone behind the scenes, resulting in the output you're seeing (Fri Sep 15 14:00:00 GMT+05:30 2017).
If you want to print in a specific format, and in a specific timezone, you'll need another formatter:
// another formatter for output
SimpleDateFormat outputFormat= new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
// output will be in Asia/Kolkata timezone
outputFormat.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));
System.out.println(outputFormat.format(meetingStartDate));
System.out.println(outputFormat.format(meetingEndDate));
The output will be:
2017-09-15T19:30:00
2017-09-15T20:30:00
Which corresponds to the same UTC dates in Kolkata timezone.
Just remember: you don't convert the Date's between timezones (because their millis values are "absolute" - they are the same for everyone in the world). You just change the String representation of those dates (the corresponding date/time in a specific timezone).
Java new Date/Time API
The old classes (Date, Calendar and SimpleDateFormat) have lots of problems and design issues, and they're being replaced by the new APIs.
In Android you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. To make it work, you'll also need the ThreeTenABP (more on how to use it here).
This new API has lots of different date/time types for each situation. In this case, the inputs have date and time, but no timezone information, so first I parse them to a org.threeten.bp.LocalDateTime, using a org.threeten.bp.format.DateTimeFormatter:
// parse the inputs
DateTimeFormatter fmt = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
LocalDateTime startDt = LocalDateTime.parse(startDateTimeUtc, fmt);
LocalDateTime endDt = LocalDateTime.parse(endDateTimeUtc, fmt);
Then I use a org.threeten.bp.ZoneOffset to convert them to UTC, and later a org.threeten.bp.ZoneId to convert this to another timezone. The result will be a org.threeten.bp.ZonedDateTime:
// input is in UTC
ZoneOffset utc = ZoneOffset.UTC;
// convert to Asia/Kolkata
ZoneId zone = ZoneId.of("Asia/Kolkata");
ZonedDateTime start = startDt.atOffset(utc).atZoneSameInstant(zone);
ZonedDateTime end = endDt.atOffset(utc).atZoneSameInstant(zone);
Then I use the same DateTimeFormatter to format the output:
System.out.println(fmt.format(start));
System.out.println(fmt.format(end));
The output is:
2017-09-15T19:30:00
2017-09-15T20:30:00
Note that I don't need to set the timezone in the formatter, because the timezone information is in the objects (they are responsible to do the conversion).

How to get the time zone from a datetime string

How can I get the time zone from a datetime string with this format 2013-08-15T13:00:00-07:00?
You could take the time offset from Andreas answer and use below sinppet to get TimeZone object.
TimeZone tmzo = TimeZone.getTimeZone("GMT"+offset);
System.out.println(tmzo.getID());
if Java 8, you can parse directly with ISO_ZONED_DATE_TIME format
String input = "2013-08-15T13:00:00-07:00";
ZonedDateTime zDateTime = ZonedDateTime.parse(input, DateTimeFormatter.ISO_ZONED_DATE_TIME);
ZoneId zone = zDateTime.getZone();
You can use a regular expression. The following assumes XML dateTime syntax:
String input = "2013-08-15T13:00:00-07:00";
Matcher m = Pattern.compile("(?:[+-]\\d{2}:\\d{2}|Z)$").matcher(input);
if (m.find())
System.out.println("Time zone: " + m.group());
else
System.out.println("No time zone found");
In Java 7 you can parse with and without TZ and than calculate the offset, taking your current TZ offset into account.
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
Date withTZ = sdf.parse("2013-08-15T13:00:00-07:00");
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
Date noTZ = sdf2.parse("2013-08-15T13:00:00-07:00");
2013-08-15T13:00:00-07:00
the last -7:00 means GMT-7
That is MST (Mountain Standard Time)
That timezone is using in US and Canada

How do I convert a String in a different timezone to UTC using Joda-Time

I managed to convert a valid date string in a different timezone to UTC as follows.
String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
DateTimeFormatter DATETIME_FORMATTER = DateTimeFormat.forPattern(DATE_FORMAT);
DateTimeZone dateTimeZone = DateTimeZone.forID("-03:00");
//date is 2000-01-01 00:00:00 -03:00
DateTime date = DATETIME_FORMATTER.withZone(dateTimeZone).parseDateTime("2000-01-01 00:00:00"));
System.out.println("Current date is: " + date.toString());
//now convert to UTC
DateTime convertedDate = date.toDateTime(DateTimeZone.UTC);
System.out.println("Converted date: " + date.toString());
The result is
Current date is: 2000-01-01T00:00:00.000-03:00
Converted date: 2000-01-01T03:00:00.000Z
Is there a shorter/better way of doing this? I want the final date to be a Joda-Time DateTime object.
You can convert the time zone of any DateTime using withZone(). If the input string doesn't specify the time-zone offset then you have to add it as you are doing, so your code is fairly optimal.
One improvement over your example code might be replacing the hard-coded "-3:00" offset with a time zone name. That would allow Joda-Time to make adjustments for any possible Daylight Saving Time (DST). See doc for DateTimeZone.forID().
This:
DateTimeZone dateTimeZone = DateTimeZone.forID("America/Sao_Paulo");
instead of this:
DateTimeZone dateTimeZone = DateTimeZone.forID("-03:00");
Time Zone list (possibly outdated, read note):
http://joda-time.sourceforge.net/timezones.html

Categories