6

As per Google App Engine flexible docs, for any incoming request, as a service to the app, App Engine adds the following headers to all requests:

X-AppEngine-Country  as an ISO 3166-1 alpha-2 country code
X-AppEngine-Region    as an ISO-3166-2 standard
X-AppEngine-City
X-AppEngine-CityLatLong
X-Cloud-Trace-Context
X-Forwarded-For: [CLIENT_IP(s)], [global forwarding rule IP]
X-Forwarded-Proto [http | https]

Is there anyway I can get timezone offset using above info from request header using Java?

thedp
  • 8,350
  • 16
  • 53
  • 95
zeeshan ansari
  • 381
  • 3
  • 16

2 Answers2

2

Add below to the pom.xml

  <dependency>
    <groupId>net.iakovlev</groupId>
    <artifactId>timeshape</artifactId>
    <version>2018d.1</version>
  </dependency>

And then run below type of code

package taruntest;

import net.iakovlev.timeshape.TimeZoneEngine;

import java.time.ZoneId;
import java.util.Optional;

public class ZoneInfo {
    public static TimeZoneEngine engine = null;
    private static Optional<ZoneId> ZoneID;

    public static void main(String[] args) {
        ZoneID = getZoneIdFromLatLong("12.971599,77.594563");
        System.out.println(ZoneID.toString());
    }

    public static Optional<ZoneId> getZoneIdFromLatLong(String latLong) {
        if (engine == null)
        {
            engine = TimeZoneEngine.initialize();
        }
        String[] latLongArr = latLong.split(",");
        double _lat = Double.parseDouble(latLongArr[0]);
        double _long = Double.parseDouble(latLongArr[1]);

        Optional<ZoneId> maybeZoneId = engine.query(_lat, _long);

        return maybeZoneId;
    }
}

The result is

Optional[Asia/Kolkata]

You can get your current coords using

https://mylocationtest.appspot.com/

Tarun Lalwani
  • 142,312
  • 9
  • 204
  • 265
  • net.iakovlev/timeshape is realtively slow to initialize and needs a lot of space to keep the parsed timezone boundary database in memory. Will it work properly in the Google App-Engine environment? – jarnbjo May 02 '18 at 14:03
  • Not sure, will need to be deployed and checked. I don't use GAE, so can't test that out – Tarun Lalwani May 02 '18 at 14:16
  • @jarnbjo I have tested my solution (other answer) in GAE environment and was working fast. – Rubén C. May 03 '18 at 10:42
  • Author of Timeshape here. The current version of Timeshape (`2018d.4`) uses roughly 128 MB of heap memory for the whole world, as measured by JOL (http://openjdk.java.net/projects/code-tools/jol/). You can limit this further if you care only about some region of the world by initializing it with a bounding box: `TimeZoneEngine.initialize(double minlat, double minlon, double maxlat, double maxlon)`. As for initialization time, it takes less than 4 seconds on my computer (Intel Core i5-6600). Hope this helps. – Haspemulator Jul 14 '18 at 05:11
-1

You can get timezone offset using App Engine flexible headers’ information. Use this code I have created based on App Engine flexible Java quickstart to extract and check the headers information:

 package com.example.appengine.gettingstartedjava.helloworld;

  import java.io.IOException;
  import java.io.PrintWriter;

  import javax.servlet.annotation.WebServlet;
  import javax.servlet.http.HttpServlet;
  import javax.servlet.http.HttpServletRequest;
  import javax.servlet.http.HttpServletResponse;

   // [START example]
  @SuppressWarnings("serial")
  @WebServlet(name = "helloworld", value = "/" )
  public class HelloServlet extends HttpServlet {

      @Override
      public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
      PrintWriter out = resp.getWriter();
     out.println("Hello, world - Flex Servlet");

      String country = req.getHeader("X-AppEngine-Country");
      String region = req.getHeader("X-AppEngine-Region");
      String city = req.getHeader("X-AppEngine-City");
      Float cityLatLong = Float.valueOf(req.getHeader("X-AppEngine-CityLatLong"));   

      out.println("Country: " + country);
      out.println("Region: " + region);
      out.println("City: " + city);
      out.println("CityLatLong: " + cityLatLong);
    } 
  } 
  // [END example]

There is a official Java class to get the timezone once the region is defined: ZonedDateTime. Find an example here that uses it.

ZonedDateTime klDateTime = ldt.atZone(ZoneId.of("Asia/Kuala_Lumpur"));

Notice that you have to transform the headers to a ZoneId legible string, adding the continent before the city. You could read a continent key based on a city type containing them in a Map of List using HashMap, with the continents as keys and the cities in lists, each list assigned to one continent.

Map<String, List<String>> hm = new HashMap<String, List<String>>();

Rubén C.
  • 1,098
  • 6
  • 16