5

I try convert UTC time to local time , minute work well but hour always have 1hour later, for example if UTC time is 04:55 , my phone clock is 9:25 but my code generate 8:25

   String dateStr = "04:55";
        SimpleDateFormat df = new SimpleDateFormat("HH:mm");
        df.setTimeZone(TimeZone.getTimeZone("UTC"));
        Date date = null;
        try {
            date = df.parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        df.setTimeZone(TimeZone.getDefault());
        String formattedDate = df.format(date);

        time.setText(String.valueOf(formattedDate));
Erfan
  • 3,059
  • 3
  • 22
  • 49
  • Whats your local time zone? – Arti Patel Jun 02 '18 at 05:05
  • @Artipatel iran – Erfan Jun 02 '18 at 05:06
  • Can you check the time zone difference? How much does it show? – Binary Baba Jun 02 '18 at 05:10
  • 1
    Daylight saving time? – Cyber Tailor Jun 02 '18 at 05:13
  • @RickSanchez read my example in question then you understand – Erfan Jun 02 '18 at 05:23
  • https://stackoverflow.com/questions/17677546/convert-utc-into-local-time-on-android – Vishal Thakkar Jun 02 '18 at 05:25
  • 1
    https://stackoverflow.com/questions/44517898/utc-to-local-time-in-millis-using-jodatime – Vishal Thakkar Jun 02 '18 at 05:26
  • I meant, check programmatically, the time zone difference may not be +4:30. – Binary Baba Jun 02 '18 at 05:26
  • I would suggest user jodatime if possible its good library for datetime – Vishal Thakkar Jun 02 '18 at 05:27
  • 3
    UTC+03:30 Iran Standard Time UTC+04:30 Iran Daylight Time. ( from -https://en.wikipedia.org/wiki/UTC%2B03:30 ) I think its considering standard time for Iran. – Arti Patel Jun 02 '18 at 05:33
  • 1
    @erfan Post further details as edits to your Question rather than as Comments. Do not expect the reader to dredge through the comments to decipher your question/issue. – Basil Bourque Jun 03 '18 at 00:04
  • 1
    FYI, the troublesome old date-time classes such as [`java.util.Date`](https://docs.oracle.com/javase/10/docs/api/java/util/Date.html), [`java.util.Calendar`](https://docs.oracle.com/javase/10/docs/api/java/util/Calendar.html), and `java.text.SimpleDateFormat` are now [legacy](https://en.wikipedia.org/wiki/Legacy_system), supplanted by the [*java.time*](https://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html) classes built into Java 8 and later. See [*Tutorial* by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). – Basil Bourque Jun 03 '18 at 00:07
  • 1
    Joda-Time is no poor suggestion, @VishalThakkar, but [ThreeTenABP](https://github.com/JakeWharton/ThreeTenABP)/`java.time` is even better. And more future-proof since Joda-Time is in maintenance mode. – Ole V.V. Jun 04 '18 at 08:10

4 Answers4

8

No DST in Iran in 1970

The time zone for Iran, Asia/Tehran, observes Daylight Saving Time (DST) in the summer of 2018 but did not do so back in 1970.

In summer of 2018, Iran is four and a half hours ahead of UTC rather than three and a half. So adjusting from 4:55 in UTC should result in 9:25 on a summer day, not 8:25.

System.out.println(
        OffsetDateTime.of(
                LocalDate.of( 2018 , Month.JUNE , 1 ) ,
                LocalTime.parse( "04:55" ) ,
                ZoneOffset.UTC
        )
       .atZoneSameInstant(
           ZoneId.of( "Asia/Tehran" )
       )
);

2018-06-01T09:25+04:30[Asia/Tehran]

But I suspect your code is defaulting to the epoch reference date of first moment of 1970 in UTC when parsing your string, 1970-01-01T00:00:00Z, because you are abusing that class in trying to parse a time-of-day without specifying a date.

In 1970, Iran did not observe Daylight Saving Time (DST). So the offset was three and a half hours ahead of UTC in summer of 1970 versus four and a half hours ahead of UTC in summer of 2018.

System.out.println(
    OffsetDateTime.of(
        LocalDate.EPOCH ,
        LocalTime.parse( "04:55" ) ,
        ZoneOffset.UTC
    )
        .atZoneSameInstant(
            ZoneId.of( "Asia/Tehran" )
        )
);

1970-01-01T08:25+03:30[Asia/Tehran]

Wrong classes

You are using the wrong classes.

You want to represent a time-of-day value. So you should be using a time-of-day class. But you are using a date-with-time-of-day class, java.util.Date.

You are using troublesome badly-designed date-time classes, java.util.Date & java.text.SimpleDateFormat. These were supplanted years ago by the java.time classes. Avoid the legacy classes entirely. Use only the classes found in the java.time package.

Time-of-day

Parse a time-of-day string.

LocalTime.parse( "04:55" )

Get the current time-of-day.

LocalTime.now()                  // Capture the current time of day per the JVM’s current default time zone.

Better to make explicit your intention to use the JVM’s current default time zone.

LocalTime.now(
    ZoneId.systemDefault()       // Capture the current time of day by explicitly asking for the JVM’s current default time zone.
)

Or specify a particular time zone.

LocalTime.now( 
    ZoneId.of( "Asia/Kabul" )  // Capture the current time-of-day as seen in the wall-clock time used by the people of a particular region (a time zone).
)

9:25

Get the current time-of-day in UTC.

LocalTime.now( 
    ZoneOffset.UTC
)

04:55

LocalTime

If you have an input string such as "04:55", parse as a LocalTime object. This class represents a time-of-day without a date and without a time zone.

String input = "04:55" ;
LocalTime lt = LocalTime.parse( input ) ;

Terminology

I try convert UTC time to local time

Your phrase “local time” has a specific meaning in date-time handling. Unfortunately that meaning is the opposite of your intention. The word “local” as seen in the *java.time.Local…” classes mean any locality or all localities rather than any one particular locality.

So a LocalTime object has no real meaning until attached to a date and placed in the context of a time zone (or offset-from-UTC).

Time zones

if UTC time is 04:55 , my phone clock is 9:25

That means your JVM’s current default time zone is using an offset-from-UTC four and a half hours ahead of UTC, +04:30. According to this list of time zones as managed by the IANA, there are only one time zone currently using that offset: Asia/Kabul.

To represent the current moment fully, you need a date and a time-of-day and a zone/offset. To capture the current moment, use Instant. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).

Instant instant = Instant.now() ;  // Capture the current moment in UTC.

To see that same moment in your time zone, apply a ZoneId to get a ZonedDateTime.

ZoneId zKabul = ZoneId.of( "Asia/Kabul" ) ;
ZonedDateTime zdt = instant.atZone( zKabul ) ;

If you really want only the time-of-day portion of that value, extract a LocalTime. This might be useful for rendering in a user-interface, but is not likely useful in your business logic.

LocalTime lt = zdt.toLocalTime() ;  // Extract just the time-of-day as seen in the wall-clock time used by the people of this region (this time zone).

As a shortcut, you could call LocalTime.now:

LocalTime lt = LocalTime.now( zKabul ) ;

Iran time

Later in your comments you explain your intended time zone is Asia/Tehran, time in Iran. Currently, Iran observes Daylight Saving Time (DST), which may be the source of your confusion. While standard offset if +03:30 (three and half hours ahead of UTC), between March 22 and September 22 the offset is +04:30, one more hour further ahead of UTC.

This is exactly why you should specify your desired/expected time zone. For casual use, you can use the JVM’s current default time zone. But know that default can change at any moment during runtime. And the default may not be what you intend. For critical usage, always confirm with the user their intended time zone.

Let's build up a date-time for June 1st with your example time 4:55 in UTC. We can use the constant ZoneOffset.UTC. When using merely an offset-from-UTC (an offset of zero in this case), use OffsetDateTime. An offset-from-UTC is merely a number of hours and minutes, nothing more, nothing less. In contrast, a time zone is a history of past, present, and future changes to the offset used by the people of a specific region.

LocalTime lt = LocalTime.parse( "04:55" ) ;
LocalDate ld = LocalDate.of( 2018 , Month.JUNE , 1 ) ;
OffsetDateTime odt = OffsetDateTime.of( ld , lt , ZoneOffset.UTC ) ;

odt.toString(): 2018-06-01T04:55Z

Adjust into the zone Asia/Tehran by applying a ZoneId to get a ZonedDateTime. Same moment, same point on the timeline, but a different wall-clock time.

ZoneId zTehran = ZoneId.of( "Asia/Tehran" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( zTehran );

zdt.toString(): 2018-06-01T09:25+04:30[Asia/Tehran]

Note the time-of-day in summer shows as 9 hour, not 8.

Try the same code with month of January, when DST is not in effect.

LocalTime lt = LocalTime.parse( "04:55" );
LocalDate ld = LocalDate.of( 2018 , Month.JANUARY , 1 );
OffsetDateTime odt = OffsetDateTime.of( ld , lt , ZoneOffset.UTC );
ZoneId zTehran = ZoneId.of( "Asia/Tehran" );
ZonedDateTime zdt = odt.atZoneSameInstant( zTehran );

zdt.toString(): 2018-01-01T08:25+03:30[Asia/Tehran]

Now we see an hour of 8.

Zone names

Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).

ZoneId z = ZoneId.of( "America/Montreal" ) ;  

If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the JVM’s current default is applied implicitly. Better to be explicit, as the default may be changed at any moment during runtime by any code in any thread of any app within the JVM.

ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
4
 df.setTimeZone(TimeZone.getDefault());

to

 df.setTimeZone(TimeZone.getTimeZone("GMT+4:30"));

working code

String dateStr = "04:55";
                SimpleDateFormat df = new SimpleDateFormat("HH:mm");
                df.setTimeZone(TimeZone.getTimeZone("UTC"));
                Date date = null;
                try {
                    date = df.parse(dateStr);
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                df.setTimeZone(TimeZone.getTimeZone("GMT+4:30"));
                String formattedDate = df.format(date);


                System.out.println(formattedDate);
                //time.setText(String.valueOf(formattedDate));

        }

output i got 9:25

Venki WAR
  • 1,997
  • 4
  • 25
  • 38
  • oh..It's working in my IDE.please verify your imported classes – Venki WAR Jun 02 '18 at 05:29
  • I'm using this classes import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.TimeZone; – Venki WAR Jun 02 '18 at 05:30
  • yes sir i import this classes correctly but not woking – Erfan Jun 02 '18 at 05:42
  • execute this code in normal java code (using main()) – Venki WAR Jun 02 '18 at 05:58
  • i change "GMT+4:30" to "GMT+2:30" and work , but i am nerves about this +2:30 when time two time in year changed in my country and so many else – Erfan Jun 02 '18 at 06:04
  • check in mobile what time zone set – Venki WAR Jun 02 '18 at 06:06
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/172282/discussion-between-erfan-and-venki-war). – Erfan Jun 02 '18 at 06:11
  • FYI, the troublesome old date-time classes such as [`java.util.Date`](https://docs.oracle.com/javase/10/docs/api/java/util/Date.html), [`java.util.Calendar`](https://docs.oracle.com/javase/10/docs/api/java/util/Calendar.html), and `java.text.SimpleDateFormat` are now [legacy](https://en.wikipedia.org/wiki/Legacy_system), supplanted by the [*java.time*](https://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html) classes built into Java 8 and later. See [*Tutorial* by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). – Basil Bourque Jun 03 '18 at 00:07
3

Try this method

public static String convertUTCtoLocalTimeZone(String date, String date_formate) {
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat(date_formate,Locale.getDefault());
    Date myDate = null;
    try {
        simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
        myDate = simpleDateFormat.parse(date);
    } catch (ParseException e) {
        e.printStackTrace();
    }

    return new SimpleDateFormat(date_formate, Locale.getDefault()).format(myDate); // Note: Use new DateFormat
}
Jay Thummar
  • 2,281
  • 1
  • 14
  • 22
1

Try below method:

  private String convertDateToUserTimeZone(String serverDate) {
    String ourdate;

    try {
        SimpleDateFormat serverFormatter = new SimpleDateFormat(
                "yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.UK);
        serverFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
        Date value = serverFormatter.parse(serverDate);
        TimeZone timeZone = TimeZone.getTimeZone("Asia/Kolkata");
//            SimpleDateFormat dateFormatter = new SimpleDateFormat(serverdateFormat, Locale.UK); //this format changeable
            serverFormatter.setTimeZone(timeZone);
            ourdate = serverFormatter.format(value);

        //Log.d("OurDate", OurDate);
    } catch (Exception e) {
        ourdate = "00-00-0000 00:00";
    }
    return ourdate;
}

All Android supported Timezone Android Timezone

I would suggest JodaTime Lib for Date time.Its have rich useful features.

Vishal Thakkar
  • 2,117
  • 2
  • 16
  • 33
  • method not woking – Erfan Jun 02 '18 at 05:42
  • You are using troublesome old classes that were supplanted years ago by the *java.time* classes. Likewise, Joda-Time project is in maintenance mode, with its team advising migration to the *java.time* classes. – Basil Bourque Jun 02 '18 at 18:17