Search code examples
javaandroidtimezoneutc

How to convert UTC time to local time in android for sunset time


I am trying to get the sunset time for the users in there local time. I get the sunset time in UTC from sunrise-sunset.org. Then I convert it to local time, then I account for daylight savings time and then I convert it to regular time.

The problem is it comes out hours off.

Edited For example:

In the app the user can set there location to anywhere in the world, let's say they set it to Springfield MO(USA). It returns 04:57:31 AM, after I convert it and what not it comes out to 5:57 AM, even though it should say 4:57 PM. That is for API 30.

Now what makes that even more strange is if I use a API 22 phone it comes out as 7:57 PM.

I needed to support API 21 to API 30(Android 11).

Also it keeps returning daylight savings time as on, when it's not.

   public void RequestSunsetTime(String lat, String lng){

        // set loading text
        sunsetTimeTextView.setText(R.string.loading_text);

        ProjectRepository projectRepository = new ProjectRepository();
        String url = "https://api.sunrise-sunset.org/json?lat=" + lat + "&lng=" + lng + "&date=today";
        projectRepository.requestDataPartTwo(url, new ProjectRepository.VolleyResponseListenerForTwo() {
            @Override
            public void onResponse(String UTCtime) {

                // convert utc time to local time
                String time = UTCtime;
                System.out.println("== TIME ==" + time);


                try {
                    SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss a", Locale.ENGLISH);
                    df.setTimeZone(TimeZone.getTimeZone("UTC"));
                    Date  _date = df.parse(UTCtime);
                    df.setTimeZone(TimeZone.getDefault());
                    System.out.println(">>>>>>>>>>> Time zone: " + TimeZone.getDefault());
                    time = df.format(_date);
                    System.out.println(">>>>>>>>>>> time: " + time);

                    // convert army time to standard time
                    String[] timeParts = time.split(":"); // convert to array

                    // fetch
                    int hours = Integer.parseInt(timeParts[0]);
                    System.out.println(">>>>> army time hours: " +hours);
                    int minutes = Integer.parseInt(timeParts[1]);
                 

                    // --- *.getDSTSavings()* adds time for day light saving time
                    int timeForDST = (((TimeZone.getDefault().getDSTSavings() / 1000) / 60) / 60);
                 
                    System.out.println(">>>>>>>>>>> time: " + time);

                    // calculate
                    String  timeValue = "";

                    if (hours > 0 && hours <= 12) {
                        timeValue= "" + hours;
                    } else if (hours > 12) {
                        timeValue= "" + (hours - 12);
                    } else if (hours == 0) {
                        timeValue= "12";
                    }

                    if(timeForDST != 0){
                        int num = Integer.parseInt(timeValue);
                        timeValue =String.valueOf(num + timeForDST);
                    }

                    timeValue += (minutes < 10) ? ":0" + minutes : ":" + minutes;  // get minutes
                 
                    timeValue += (hours >= 12) ? " PM" : " AM";  // get AM/PM

                    time = timeValue;

                } catch (ParseException e) {
                    e.printStackTrace();
                }
                System.out.println(">>>>>>>>>> Final Time: " + time);
                // save
       
              
            }

          

        });

    }

Thank you in advance:)


Solution

  • You are working much too hard.

    Never use the terrible legacy date-time classes such as SimpleDateFormat, TimeZone, Date, and Calendar classes. Use only the java.time classes.

    I’m not clear on what format of text you receive. I’ll assume it is standard ISO 8601 format YYYY-MM-DDTHH:MM:SSZ. (If not, edit your Question for clarity.)

    Instant instant = Instant.parse( "2022-01-23T12:34:56.123456789Z" ) ;
    

    If desired, lop off unneeded detail.

    instant = instant.truncatedTo( ChronoUnit.MINUTES ) ;
    

    Adjust from an offset of zero hours-minutes-seconds from UTC to a particular time zone.

    ZoneId z = ZoneId.of( "America/Edmonton" ) ;  // Or ‘ZoneId.systemDefault()`. 
    ZonedDateTime zdt = instant.atZone( z ) ;
    

    Extract the time of day.

    LocalTime lt = zdt.toLocalTime() ;
    

    Generate text in automatically localized format.

    DateTimeFormatter f = DateTimeFormatter.ofLocalizedTime( FormatStyle.SHORT ).withLocale( Locale.CANADA_FRENCH ) ;
    String output = lt.format( f ) ;
    

    See this code run live at IdeOne.com.

    These classes are built into Android 26+. For earlier Android, use the latest tooling with its “API desugaring” to access most of the java.time functionality.