# How to get latitude /longitude in Degree Minute Second (DMS) using QGIS field calculator?

I have come up with the following expression to convert 5.1234 to 5° 7`24.24"

toint (\$x) || '° ' || toint(((\$x) - toint (\$x)) * 60) ||'`' || substr( (tostring((((\$x) - toint (\$x)) * 60) - toint(((\$x) - toint (\$x)) * 60)) * 60),1,5) || '"'

Here’s the problem : for some points such as 5.1234, it works. but for others, it doesn’t. I suspect the problem is the integer conversion which round up the decimal figures instead of truncating it.

Is there any other option? thanks.

-
I can suggest a workaround. Not optimal, but if you are stuck right now, you can get your work done. Right click and Save As a CSV. Open the CSV in Excel or Google Docs, enter your formula (which should be cleaner and easier). Delete all fields except a unique identifier and converted DMS strings. Save it. Do a table join with existing layer and you are set. – spatialthoughts Jul 2 '12 at 10:46
Be careful with negative inputs. – whuber Jul 2 '12 at 11:37
Thanks for the tips guys. – Obsidianz Jul 2 '12 at 22:22
Just to add to spatialthought's answer: rounding down to the nearest degree will work in Excel using the FLOOR() function. – Micha Jul 3 '12 at 11:23

I like the expression you've put together - probably no solution in QGIS 1.8, but in QGIS 1.9-dev there's a `floor()` rounding function which rounds down. For D°M'S'':

``````(CASE WHEN \$x < 0 THEN '-' ELSE '' END) || floor (abs(\$x)) || '° ' || floor(((abs(\$x)) - floor (abs(\$x))) * 60) ||'\'' || substr( (tostring((((abs(\$x)) - floor (abs(\$x))) * 60) - floor(((abs(\$x)) - floor (abs(\$x))) * 60)) * 60),1,5) || '"'
``````

Note the escaped apostrophe (`\'`).

For D°M.MMM':

``````(CASE WHEN \$x < 0 THEN '-' ELSE '' END) || floor (abs(\$x)) || '° ' || ((abs(\$x) - floor(abs(\$x))) * 60) ||'\''
``````

To limit the number of displayed decimal minutes, substitute # in the expression below with the number of digits:

``````(CASE WHEN \$x < 0 THEN '-' ELSE '' END) || floor (abs(\$x)) || '° ' ||  format_number( (abs(\$x) - floor(abs(\$x))) * 60, #) ||'\'
``````
-
Just out of curiosity, how would the formula look like for Degrees, Minutes? – mace Jan 8 '15 at 13:32
Added an example; this works in QGIS 2.6 (and probably anything 2.0 and up) but there may be more elegant formatting functions available now. – Simbamangu Jan 9 '15 at 4:46
Just one pitfall: Your formula only works for positive values of Easting and Northing. Negative are one too small. And I wonder how 0.5° E and 0.5° W may be distinguished. floor(+/-0.5) will always be 0, not -0. – AndreJ Jan 9 '15 at 6:18
Aaargh. The pitfalls of insufficient testing ... and here's me working in the southern (negative) hemisphere, too. Updating shortly. – Simbamangu Jan 9 '15 at 7:17

The modulo operator can be used to do truncation, but the resulting expression would be very ugly. It is prettier to use string substitution, but unfortunately QGIS doesn't expose any strpos or similar functions. Use `regexp_replace(\$x, '\\..*', '')` to get the whole part and `regexp_replace(\$x, '^[0-9]*\\.', '')` to get the decimal part. Use `toreal` instead of `toint` for calculations with the second expression to make sure there will be no rounding.

-
Didn't have a strpos function but does now ;) github.com/qgis/Quantum-GIS/commit/… – Nathan W Jul 2 '12 at 10:04
tsk tsk tsk, so much whitespace noise. – lynxlynxlynx Jul 2 '12 at 10:22
Yeah ignore that first bit it was just a bit of clean up unrelated to the new function. – Nathan W Jul 2 '12 at 10:25
Ugly it is... will try to work it out. – Obsidianz Jul 2 '12 at 22:39