Convert indian time zone to local time - android

In my app I am getting time from server in API in IST timezone, I want to show time in device's local time zone.
Below is my code for this but it seems its not working.
SimpleDateFormat serverSDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SimpleDateFormat utcSDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SimpleDateFormat localSDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
serverSDF.setTimeZone(TimeZone.getTimeZone("Asia/Calcutta"));
utcSDF.setTimeZone(TimeZone.getTimeZone("UTC"));
localSDF.setTimeZone(TimeZone.getDefault());
Date serverDate = serverSDF.parse(dateString);
String utcDate = utcSDF.format(serverDate);
Date localDate = localSDF.parse(utcDate);
From server I am getting time "2018-02-28 16:04:12" in IST and the code above displays "Wed Feb 28 10:34:12 GMT+05:30 2018".

The other answer uses GMT+05:30, but it's much better to use a proper timezone such as Asia/Kolkata. It works now because India currently uses the +05:30 offset, but it's not guaranteed to be the same forever.
If someday the government decides to change the country's offset (which already happened in the past), your code with a hardcoded GMT+05:30 will stop working - but a code with Asia/Kolkata (and a JVM with the timezone data updated) will keep working.
But today there's a better API to manipulate dates, see here how to configure it: How to use ThreeTenABP in Android Project
This is better than SimpleDateFormat, a class known to have tons of problems: https://eyalsch.wordpress.com/2009/05/29/sdf/
With this API, the code would be:
String serverDate = "2018-02-28 16:04:12";
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime istLocalDate = LocalDateTime.parse(serverDate, fmt);
// set the date to India timezone
String output = istLocalDate.atZone(ZoneId.of("Asia/Kolkata"))
// convert to device's zone
.withZoneSameInstant(ZoneId.systemDefault())
// format
.format(fmt);
In my machine, the output is 2018-02-28 07:34:12 (it varies according to the default timezone of your environment).
Although it seems complicated to learn a new API, in this case I think it's totally worth it. The new API is much better, easier to use (once you learn the concepts), less error-prone, and fix lots of problems of the old API.
Check Oracle's tutorial to learn more about it: https://docs.oracle.com/javase/tutorial/datetime/

Update: Check this answer by #istt which uses modern Java8 date-time api.
You don't need to change format in UTC first. You can simply use:
SimpleDateFormat serverSDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SimpleDateFormat localSDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
serverSDF.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));
localSDF.setTimeZone(TimeZone.getDefault());
String localDate = localSDF.format(serverSDF.parse(dateString));

Related

How can I compare a string (of a given format) to current date?

I want to compare a date string (that I get form a viewHolder) with this format "dd-MM-yyyy HH:mm" to current date and time but I keep getting java.lang.IllegalArgumentException: Cannot format given Object as a Date. This is how I tried:
SimpleDateFormat dateAndTimeFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm", Locale.ROOT);
LocalDate localDate = LocalDate.now();
String currentDateAndTime = dateAndTimeFormat.format(localDate.toString());
if(viewHolder.time.getText().toString().equals(currentDateAndTime)){
//irrelevant
}
SimpleDataFormat.format(...) takes a Date object as its first parameter. You're passing in a String because you're calling toString() on it. Try this:
SimpleDateFormat dateAndTimeFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm", Locale.ROOT);
String currentDateAndTime = dateAndTimeFormat.format(new Date());
if (viewHolder.time.getText().toString().equals(currentDateAndTime)) {
//irrelevant
}
Go all-in on java.time, the modern Java dat and time API.
DateTimeFormatter dateAndTimeFormat = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm", Locale.ROOT);
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.systemDefault());
String currentDateAndTime = zdt.format(dateAndTimeFormat);
System.out.println(currentDateAndTime);
When I ran the code just now using Pacific/Honolulu time zone as my default, the output was:
01-05-2020 08:47
What went wrong in your code?
Two things were wrong:
A LocalDate is just a date without time of day, so there is no way you can format it into a string that includes hour of day and minute. Instead use ZonedDateTime, OffsetDateTime or LocalDateTime.
It’s good to use LocalDate or another class from java.time, the modern Java date and time API. The modern classes and the outdated SimpleDateFormat don’t work together. To format a date and/or time object from java.time you need to use the modern DateTimeFormatter class. Which is good because SimpleDateFormat is a notoriously troublesome class that you should not want to use under any circumstances. What tends to fool us is that your code actually compiled, which gives the impression that it should work. It was never meant to. SimpleDateFormat inherits the format(Object) method from Format, a general superclass for formatting many kinds of objects, which is why the argument is declared to be Object, not Date (another outdated class).

Convert String in 12 (PM /AM)Hour AM PM Time to 24 Hour time android

I have a problem in convert time coming from server and I want to convert it to 24 hour. I'm using the following code:
String timeComeFromServer = "3:30 PM";
SimpleDateFormat date12Format = new SimpleDateFormat("hh:mm a");
SimpleDateFormat date24Format = new SimpleDateFormat("HH:mm");
try {
((TextView)findViewById(R.id.ahmad)).setText(date24Format.format(date12Format.parse(timeComeFromServer)));
} catch (ParseException e) {
e.printStackTrace();
}
There is the error:
Method threw 'java.text.ParseException' exception.)
Detailed error message is:
Unparseable date: "3:30 PM" (at offset 5)
But if I replace PM to p.m. it works without any problem like this:
timeComeFromServer = timeComeFromServer.replaceAll("PM", "p.m.").replaceAll("AM", "a.m.");
Can any one tell me which is the correct way?
SimpleDateFormat uses the system's default locale (which you can check using the java.util.Locale class, calling Locale.getDefault()). This locale is device/environment specific, so you have no control over it and can have different results in each device.
And some locales might have a different format for AM/PM field. Example:
Date d = new Date();
System.out.println(new SimpleDateFormat("a", new Locale("es", "US")).format(d));
System.out.println(new SimpleDateFormat("a", Locale.ENGLISH).format(d));
The output is:
p.m.
PM
To not depend on that, you can use Locale.ENGLISH in your formatters, so you won't depend on the system/device's default configuration:
String timeComeFromServer = "3:30 PM";
// use English Locale
SimpleDateFormat date12Format = new SimpleDateFormat("hh:mm a", Locale.ENGLISH);
SimpleDateFormat date24Format = new SimpleDateFormat("HH:mm");
System.out.println(date24Format.format(date12Format.parse(timeComeFromServer)));
The output is:
15:30
The second formatter doesn't need a specific locale as it's not dealing with locale specific information.
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.
One detail is that SimpleDateFormat always works with Date objects, which has the full timestamp (the number of milliseconds since 1970-01-01T00:00Z), and both classes implicity use the system default timezone behind the scenes, which can mislead you and generate unexpected and hard to debug results. But in this specific case, you need only the time fields (hour and minutes) and there's no need to work with timestamp values. The new API has specific classes for each case, much better and less error prone.
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 ThreeTenABP (more on how to use it here).
You can use a org.threeten.bp.format.DateTimeFormatter and parse the input to a org.threeten.bp.LocalTime:
String timeComeFromServer = "3:30 PM";
DateTimeFormatter parser = DateTimeFormatter.ofPattern("h:mm a", Locale.ENGLISH);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm");
LocalTime time = LocalTime.parse(timeComeFromServer, parser);
System.out.println(time.format(formatter));
The output is:
15:30
For this specific case, you could also use time.toString() to get the same result. You can refer to javadoc for more info about the backport API.

Android 12 hours Time Format getting wrong

I am using
DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy hh:mm a");
String dateAsString = dateFormat.format(gmt);
And getting String 06-06-2017 08:15 a.m.
Why I am getting a.m. instated of AM or PM?
The AM/PM/a.m. actually depends on the device. Try the same code on other devices and you might get to see a different result. If you need AM/PM only, then you need to do it manually by replacing the dots and converting it to uppercase.
It depends on the locale. If you use SimpleDateFormat (which you may not want to do, see below), I recommend you give it an explicit locale. The one you construct uses the device’s default, which explains why you get different results on different devices. If you want that, use new SimpleDateFormat("MM-dd-yyyy hh:mm a", Locale.getDefault()) so the reader knows you have thought about it. To make sure you get AM and PM, use for example new SimpleDateFormat("MM-dd-yyyy hh:mm a", Locale.ENGLISH).
Why would you not want to use SimpleDateFormat? I consider it long outdated since the much better replacement for the Java 1.0 and 1.1 classes came out with Java 8 in 2014. They have also been backported to Android Java 7 in the ThreeTenABP. Get this and write for example:
LocalDateTime gmt = LocalDateTime.of(2017, Month.JUNE, 6, 8, 15);
DateTimeFormatter dateTimeFormat = DateTimeFormatter.ofPattern("MM-dd-uuuu hh:mm a",
Locale.ENGLISH);
String dateAsString = gmt.format(dateTimeFormat);
The result is
06-06-2017 08:15 AM
To make explicit that the time is in GMT, you may use an OffsetDateTime with offset ZoneOffset.UTC.
Link: How to use ThreeTenABP in Android Project.

How can I format Date with Locale in Android

I am using SimpleDateFormat to format my date "dd Mmm yyy" format but I want Mmm to be translated to Malay. I am using below code to do so but unable to get the expected result.
SimpleDateFormat sdf = new SimpleDateFormat(format,new Locale("ms","MY"));
return sdf.format(date);
You Should Try This Way to format locale date:
DateFormat f = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.getDefault());
String formattedDate = f.format(new Date());
System.out.println("Date: " + formattedDate);
I Hope this will work. Reference link: Localized date format in Java
I had not set new Locale constructor properly to handle Malay language support.
String format = "MMM dd yyyy"
SimpleDateFormat sdf = new SimpleDateFormat(format, new Locale("ms","MY","MY"));
return sdf.format(date);
java.time
You are using old date-time classes that have proven to be poorly designed, confusing, and troublesome. They have been supplanted by the java.time classes built into Java 8 and later. Defined by JSR 310. Much of that functionality has been back-ported to Java 6 & 7 in the ThreeTen-Backport project and further adapted to Android in the ThreeTenABP project.
If you have a java.util.Date object, convert it to an Instant object, a moment on the timeline in UTC with a resolution of nanoseconds. New methods have been added to the old classes to facilitate conversion.
Instant instant = myJavaUtilDate.toInstant();
Or get the current moment. In Java 8, the current moment is captured only with millisecond resolution, despite the Instant class’ capacity for nanoseconds. In Java 9, the current moment is captured with up to nanosecond resolution (depending on your computer hardware clock capability).
Instant instant = Instant.now();
Apply a time zone for the locality whose wall-clock time you want to see. This is important even for a date-only value as the date varies around the world at any given moment. A new day dawns earlier in the east.
I choose a New Zealand time zone arbitrarily, for demonstration. Apply a ZoneId to get a ZonedDateTime object.
Use proper time zone names, never the 3-4 letter codes you see in the media such as IST or EST. Such codes are not standardized nor even unique.
ZoneId zoneId = ZoneId.of( "Pacific/Auckland" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
The time zone has nothing to do with localization into a human language such as Malay. A Locale handles that, as well as defining cultural norms to use for issues such as ordering of the elements or using period vs comma.
My example assumes you were correct in specifying the language and country/culture codes.
Locale locale = new Locale( "ms" , "MY" );
The java.time.format package has classes that can automatically localize when generating a String to represent a java.time value.
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDate( FormatStyle.MEDIUM );
When defining a formatter, remember to specify the Locale. If omitted, your JVM’s current default Locale will be applied implicitly. That default can change at any moment, even during runtime! So better to be always be explicit.
formatter = formatter.withLocale( locale );
String output = zdt.format( formatter );
23 Mei 2016
By comparison when using Locale.US:
May 23, 2016
And when using Locale.CANADA_FRENCH:
2016-05-23
I am not sure if below code works for you, its written in Scala its almost same in Java.
val malaysia = new Locale("ms","MY","MY")
val cal = Calendar.getInstance(malaysia)
val df = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, malaysia)
println(df.format(cal.getTime()))
results from above code is
Isnin 23 Mei 2016 9:55:44 AM IST
You need to do this way;
Edit 1:
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, new Locale("ms","MY"));
String formattedDate = dateFormat.format(new Date());
Hope this would help you.
This code solved my problem and get the result in Bengali.
val local = Locale("bn")
val dateFormat = DateFormat.getDateInstance(DateFormat.FULL, local)
val stringDate = dateFormat.format(date)
Log.e("", stringDate)
And the output is:
মঙ্গলবার, ২৩ ফেব্রুয়ারী, ২০২১
if you want your date to be formatted to device locale then use the below code
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date newDate = format.parse(strDate2);
long milliDate = newDate.getTime()+getCurrentTimezoneOffset();
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(milliDate);
return format.format(cal.getTime());

Get time of different Time zones on selection of time from time picker

I have an issue of converting selected hours and minutes to different time zones of countries.
Supposing if i select 10 am in India then i want to know at 10 am in india what will be the time in USA/New york and Tokyo.and Vice versa.
Any help is appreciable...
Thank you
please find the sollution below :
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy hh:mma");
TimeZone timezone = TimeZone.getDefault();
TimeZone utcTimeZone = TimeZone.getTimeZone("UTC");
Date d = new Date();
sdf.setTimeZone(timezone);
String strtime = sdf.format(d);
Log.e("str time gmt ",strtime);
sdf.setTimeZone(utcTimeZone);
strtime = sdf.format(d);
Log.e("str time utc ",strtime);
i think this will solve your problem
You can probably use Joda Time - Java date and time API. You can get the DateTimeZone depending on the Canonical ID defined in the Joda Time,
DateTimeZone zone = DateTimeZone.forID("Asia/Kolkata");
Joda Time has a complete list of Canonical ID from where you can get TimeZone depending on the Canonical ID.
So, if you want to get the local time in New York at this very moment, you would do the following
// get current moment in default time zone
DateTime dt = new DateTime();
// translate to New York local time
DateTime dtNewYork = dt.withZone(DateTimeZone.forID("America/New_York"));
For getting more idea you can refer Changing TimeZone
Try using Joda-Time library
check the org.joda.time.DateTimeZone class
Here is the API documentation for the same.
you can also get it using , Here no external API is needed
DateFormat format = new SimpleDateFormat("MMMMM d, yyyy, h:mm a");
TimeZone utc = TimeZone.getTimeZone("America/New_York");
System.out.println(utc.getID());
GregorianCalendar gc = new GregorianCalendar(utc);
Date now = gc.getTime();
System.out.println(format.format(now));
you can see more time zone on this Link
Output
America/New_York
December 29, 2012, 11:04 AM
If you don't know city name then you can also use it by Zone name as follow
DateFormat format = new SimpleDateFormat("MMMMM d, yyyy, h:mm a");
TimeZone cst = TimeZone.getTimeZone("US/Eastern");
System.out.println(cst.getID());
GregorianCalendar gc = new GregorianCalendar(cst);
Date now = gc.getTime();
format.setTimeZone(cst);
System.out.println(format.format(now))
Output
US/Eastern
December 29, 2012, 12:38 AM
Not really sure about the solution I'm going to provide but I think you can try it. GMT (Greenwich Mean Time) is a standard. I think you can keep it as a base and calculate the desired time. GMT standard is easily available too.
For example: While installing an OS like Windows XP or Windows 7, we select the time from a drop down menu. My point is, keeping this as the base, you can find the difference between the time zones in NY-US and Tokyo-Japan or vice versa as you desire it.
Hope this helps.

Categories

Resources