I'm writing a program which expects a number of lat/long points, and I convert them internally to UTM in order to do some calculations in metres.

The range of the lat/long points themselves is quite small -- about 200m x 200m. They can be relied on almost always to be within a single UTM zone (unless you get unlucky and are across the border of a zone).

However, the zone that the lat/longs are in is unrestricted. One day the program might be run for people in Australia (and oh, how many zones does even a single state lie across, and how much pain has that caused me already...), and another day for people in Mexico.

My question is -- is there a way to determine which zone a particular long/lat is in so that it may be fed into a conversion library (I currently use proj4 and also the R package `rgdal`). 

My language is R, but the answer doesn't have to be -- maybe it's just a simple calculation, or maybe I can embed a system call to the `proj` exectuable.

cheers.
['https://Stackoverflow.com/questions/9186496', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/913184/']
**Edit:** For (non-R) code that works for *all* non-polar areas on earth, see [here](https://gis.stackexchange.com/questions/13291/is-there-a-simple-way-to-compute-the-utm-zone-from-a-lat-long-point) or [here](http://www.igorexchange.com/node/927).

---

Unless you are dealing with data from a couple of exceptional areas ([Svalbard and parts of Norway](http://en.wikipedia.org/wiki/Universal_Transverse_Mercator_coordinate_system#Exceptions)), this is a simple enough calculation that you might as well just do it yourself in R. Here is [Wikipedia's description](http://en.wikipedia.org/wiki/Universal_Transverse_Mercator_coordinate_system) of how longitude relates to UTM Zone number:

> 
> The UTM system divides the surface of Earth between 80°S and 84°N latitude into 60 zones, each 6° of longitude in width. Zone 1 covers longitude 180° to 174° W; zone numbering increases eastward to zone 60 that covers longitude 174 to 180 East. 
> 
> 
> 

So, assuming that in your data longitudes to the west of the [Prime Meridian](http://en.wikipedia.org/wiki/Prime_Meridian) are encoded as running from -180 to 0 degrees, here's an R-code version of the above:

```
long2UTM <- function(long) {
    (floor((long + 180)/6) %% 60) + 1
}

# Trying it out for San Francisco, clearly in UTM Zone 10 
# in the figure in the Wikipedia article linked above
SFlong <- -122.4192
long2UTM(SFlong)
# [1] 10

```

That expression could obviously be simplified a bit, but I think in this form the logic underlying its construction is most clear. The `%% 60` bit is in there just in case some of your longitudes are greater than 180 or less than -180.
I don't know r-code but I suppose this PL/SQL code can help you with the exceptions:

```
   UTMZone := Trunc((lon - Zone0WestMeridian) / d);
    --Special Cases for Norway & Svalbard
    CASE 
    WHEN (lat > 55) AND (UTMZone = 31) AND (lat < 64) AND (lon >  2) THEN UTMZone := 32;
    WHEN (lat > 71) AND (UTMZone = 32) AND (lon <  9) THEN UTMZone := 31;
    WHEN (lat > 71) AND (UTMZone = 32) AND (lon >  8) THEN UTMZone := 33;
    WHEN (lat > 71) AND (UTMZone = 34) AND (lon < 21) THEN UTMZone := 33;
    WHEN (lat > 71) AND (UTMZone = 34) AND (lon > 20) THEN UTMZone := 35; 
    WHEN (lat > 71) AND (UTMZone = 36) AND (lon < 33) THEN UTMZone := 35;
    WHEN (lat > 71) AND (UTMZone = 36) AND (lon > 32) THEN UTMZone := 37;
    ELSE UTMZone := UTMZone;  
    END CASE;

```