# Computing UTM Zone from lat/long point

I am trying to convert a latitude/longitude point to UTM.

To define UTM projection, I need to calculate zone for the point.

I am trying to figure out the best way to do this.

One way to do this would be use longitude values to find the proper zone.

This would require lot of coding.

I am curious if there is a better way of doing this?

• You could always do a Select By Location function and select the polygon UTM Zone that the point is located inside of. Aug 9, 2011 at 15:44
• Do you need to consider all possible UTM zones (such as polar zones, etc.) or do you just want the mid-latitude zones? The latter are a simple calculation because they are evenly spaced every six degrees from -180 to +180. Aug 9, 2011 at 15:52

It's not that difficult, even if you handle the zones around Svalbard and Norway. Here's an example:

``````ZoneNumber = floor((LongTemp + 180)/6) + 1;

if( Lat >= 56.0 && Lat < 64.0 && LongTemp >= 3.0 && LongTemp < 12.0 )
ZoneNumber = 32;
endif
// Special zones for Svalbard
if( Lat >= 72.0 && Lat < 84.0 )
if  ( LongTemp >= 0.0  && LongTemp <  9.0 )
ZoneNumber = 31;
elseif( LongTemp >= 9.0  && LongTemp < 21.0 )
ZoneNumber = 33;
elseif(LongTemp >= 21.0 && LongTemp < 33.0 )
ZoneNumber = 35;
elseif(LongTemp >= 33.0 && LongTemp < 42.0 )
ZoneNumber = 37;
endif
endif
``````

Convert Latitude/Longitude to UTM (attributed to Chuck Gantz).

I haven't tried this specific code, but the algorithm looks correct.

So I had this problem today, that I needed to find the UTM zone from lat/long. I needed to do it in R, but this was one of the top google hits. So here's my R script, with tests at the end for some of the curly edge cases like Svalbard, Norway, and the poles:

``````require(tidyverse)
require(purrr)
require(testthat)

find_one_utm_zone <- function(longitude, latitude) {

# Special zones for Svalbard
if (latitude >= 72.0 && latitude <= 84.0 ) {
if (longitude >= 0.0  && longitude <  9.0)
return("31X");
if (longitude >= 9.0  && longitude < 21.0)
return("33X")
if (longitude >= 21.0 && longitude < 33.0)
return("35X")
if (longitude >= 33.0 && longitude < 42.0)
return("37X")
}
# Special zones for Norway
if (latitude >= 56.0 && latitude < 64.0 ) {
if (longitude >= 0.0  && longitude <  3.0)
return("31V");
if (longitude >= 3.0  && longitude < 12.0)
return("32V")
}

# North + South Poles

if (latitude > 84.0){
if ((longitude+180)%%360-180 < 0) {return("Y")}
if ((longitude+180)%%360-180 > 0) {return("Z")}
} else if (latitude < -80.0){
if ((longitude+180)%%360-180 < 0) {return("A")}
if ((longitude+180)%%360-180 > 0) {return("B")}
}

# Everything in the middle

if ( (latitude>-80.0) && (latitude<=84.0) ){

mid_zones <- LETTERS[c(3:8,10:14,16:24)] # C to X, skip I and O
utm_letter <- mid_zones[ min(floor( (latitude + 80) / 8 )+1 , 20) ]
utm_number <- (floor( (longitude + 180) / 6 ) %% 60) + 1 # modulo in case longitude is 0 to 360 instead of -180 to 180
utm_zone <- paste0(utm_number, utm_letter)
return(utm_zone)

} else {
stop("lat long not valid (or something else broke)")
}
}
find_utm_zone <- function(lon, lat){
purrr::map2_chr(.x = lon, .y = lat, .f = find_one_utm_zone)
}
``````

Example of use

``````locs <-
tibble(lon = c(-100,30,150, 4, 7, 22, 0, 12, -34),
lat = c(-45, 85, 12, 57, 81, 83, 5, -81, 85),
desired_utm_zone = c("14G","Z","56P", "32V" ,"31X","35X","31N", "B","Y"))

locs2 <-
locs %>%
mutate(utm_zone = find_utm_zone(lon = lon,lat = lat))
``````

Test that it worked:

``````testthat::expect_equal(locs2\$utm_zone, locs2\$desired_utm_zone)
``````