Index: ow/models/user.py
===================================================================
--- ow/models/user.py	(revision d507f75fff71fd217d2b42eeb35e65ea22b716ad)
+++ ow/models/user.py	(revision 31adfa57ce1ed36312e60622d6a3d0ddcfb98382)
@@ -33,4 +33,5 @@
         self.gender = kw.get('gender', 'female')
         self.picture = kw.get('picture', None)  # blob
+        self.timezone = kw.get('timezone', 'UTC')
         self.__password = None
         self.last_workout_id = 0
Index: ow/models/workout.py
===================================================================
--- ow/models/workout.py	(revision d507f75fff71fd217d2b42eeb35e65ea22b716ad)
+++ ow/models/workout.py	(revision 31adfa57ce1ed36312e60622d6a3d0ddcfb98382)
@@ -3,4 +3,5 @@
 from decimal import Decimal
 
+import pytz
 import gpxpy
 from repoze.folder import Folder
@@ -74,4 +75,20 @@
         return self.start.strftime('%H:%M')
 
+    def start_in_timezone(self, timezone):
+        """
+        Return a string representation of the start date and time,
+        localized into the given timezone
+        """
+        _start = self.start.astimezone(pytz.timezone(timezone))
+        return _start.strftime('%d/%m/%Y %H:%M (%Z)')
+
+    def end_in_timezone(self, timezone):
+        """
+        Return a string representation of the end date and time,
+        localized into the given timezone
+        """
+        _end = self.end.astimezone(pytz.timezone(timezone))
+        return _end.strftime('%d/%m/%Y %H:%M (%Z)')
+
     def split_duration(self):
         hours, remainder = divmod(int(self.duration.total_seconds()), 3600)
Index: ow/schemas/user.py
===================================================================
--- ow/schemas/user.py	(revision d507f75fff71fd217d2b42eeb35e65ea22b716ad)
+++ ow/schemas/user.py	(revision 31adfa57ce1ed36312e60622d6a3d0ddcfb98382)
@@ -1,4 +1,5 @@
 from pyramid.i18n import TranslationStringFactory
 from formencode import Schema, validators
+from pytz import common_timezones
 
 from ow.schemas.blob import FieldStorageBlob
@@ -74,4 +75,5 @@
     picture = FieldStorageBlob(if_emtpy=None, if_missing=None,
                                whitelist=['jpg', 'jpeg', 'png', 'gif'])
+    timezone = validators.OneOf(common_timezones, if_missing='UTC')
 
 
Index: ow/templates/dashboard.pt
===================================================================
--- ow/templates/dashboard.pt	(revision d507f75fff71fd217d2b42eeb35e65ea22b716ad)
+++ ow/templates/dashboard.pt	(revision 31adfa57ce1ed36312e60622d6a3d0ddcfb98382)
@@ -38,5 +38,5 @@
             <ul class="workout-info">
               <li>
-                <tal:c tal:content="workout.start"></tal:c>
+                <tal:c tal:content="workout.start_in_timezone(context.timezone)"></tal:c>
               </li>
               <li>
Index: ow/templates/delete_workout.pt
===================================================================
--- ow/templates/delete_workout.pt	(revision d507f75fff71fd217d2b42eeb35e65ea22b716ad)
+++ ow/templates/delete_workout.pt	(revision 31adfa57ce1ed36312e60622d6a3d0ddcfb98382)
@@ -25,14 +25,15 @@
         <input id="delete" name="delete" type="hidden" value="yes" />
 
-      <div id="workout">
+        <div id="workout"
+             tal:define="timezone request.root[request.authenticated_userid].timezone">
         <h3 tal:content="context.title"></h3>
         <ul id="" tal:attributes="id 'workout-' + context.workout_id + '-details'">
           <li>
             <tal:t i18n:translate="">Start:</tal:t>
-            <tal:c tal:content="context.start"></tal:c>
+            <tal:c tal:content="context.start_in_timezone(timezone)"></tal:c>
           </li>
           <li>
             <tal:t i18n:translate="">End:</tal:t>
-            <tal:c tal:content="context.end"></tal:c>
+            <tal:c tal:content="context.end_in_timezone(timezone)"></tal:c>
           </li>
           <li>
Index: ow/templates/edit_profile.pt
===================================================================
--- ow/templates/edit_profile.pt	(revision d507f75fff71fd217d2b42eeb35e65ea22b716ad)
+++ ow/templates/edit_profile.pt	(revision 31adfa57ce1ed36312e60622d6a3d0ddcfb98382)
@@ -99,4 +99,15 @@
         </fieldset>
 
+        <fieldset>
+            <p>
+                <label for="timezone" i18n:translate="">Timezone:</label>
+                <small i18n:translate="">
+                    All dates and times will be formatted for this timezone
+                </small>
+                ${form.errorlist('timezone')}
+                ${form.select('timezone', timezones)}
+            </p>
+        </fieldset>
+
         <p>
             ${form.submit("submit", "Save",  **{'class':"button button-normal"})}
Index: ow/templates/workout.pt
===================================================================
--- ow/templates/workout.pt	(revision d507f75fff71fd217d2b42eeb35e65ea22b716ad)
+++ ow/templates/workout.pt	(revision 31adfa57ce1ed36312e60622d6a3d0ddcfb98382)
@@ -78,12 +78,12 @@
 
       <ul id="" tal:attributes="id 'workout-' + context.workout_id + '-details'"
-          tal:define="hr context.hr; cad context.cad">
+          tal:define="hr context.hr; cad context.cad; timezone context.owner.timezone">
         <li>
           <tal:t i18n:translate="">Start:</tal:t>
-          <tal:c tal:content="context.start"></tal:c>
+          <tal:c tal:content="context.start_in_timezone(timezone)"></tal:c>
         </li>
         <li>
           <tal:t i18n:translate="">End:</tal:t>
-          <tal:c tal:content="context.end"></tal:c>
+          <tal:c tal:content="context.end_in_timezone(timezone)"></tal:c>
         </li>
         <li>
Index: ow/tests/models/test_workout.py
===================================================================
--- ow/tests/models/test_workout.py	(revision d507f75fff71fd217d2b42eeb35e65ea22b716ad)
+++ ow/tests/models/test_workout.py	(revision 31adfa57ce1ed36312e60622d6a3d0ddcfb98382)
@@ -77,4 +77,21 @@
         workout = Workout(start=start_date)
         assert workout.start_time == start_date.strftime('%H:%M')
+
+    def test_start_in_timezone(self):
+        start_date = datetime.now(tz=timezone.utc)
+        str_start_date = start_date.strftime('%d/%m/%Y %H:%M (%Z)')
+        workout = Workout(start=start_date)
+        assert workout.start_in_timezone('UTC') == str_start_date
+        assert workout.start_in_timezone('Europe/Madrid') != str_start_date
+        assert workout.start_in_timezone('America/Vancouver') != str_start_date
+
+    def test_end_in_timezone(self):
+        start_date = datetime.now(tz=timezone.utc)
+        end_date = start_date + timedelta(minutes=60)
+        str_end_date = end_date.strftime('%d/%m/%Y %H:%M (%Z)')
+        workout = Workout(start=start_date, duration=timedelta(minutes=60))
+        assert workout.end_in_timezone('UTC') == str_end_date
+        assert workout.end_in_timezone('Europe/Madrid') != str_end_date
+        assert workout.end_in_timezone('America/Vancouver') != str_end_date
 
     def test_split_duration(self):
Index: ow/tests/views/test_user.py
===================================================================
--- ow/tests/views/test_user.py	(revision d507f75fff71fd217d2b42eeb35e65ea22b716ad)
+++ ow/tests/views/test_user.py	(revision 31adfa57ce1ed36312e60622d6a3d0ddcfb98382)
@@ -259,5 +259,5 @@
         # loaded user profile
         data = ['firstname', 'lastname', 'email', 'nickname', 'bio',
-                'birth_date', 'height', 'weight', 'gender']
+                'birth_date', 'height', 'weight', 'gender', 'timezone']
         assert list(response['form'].data.keys()) == data
         # and check the email to see data is properly loaded
Index: ow/views/user.py
===================================================================
--- ow/views/user.py	(revision d507f75fff71fd217d2b42eeb35e65ea22b716ad)
+++ ow/views/user.py	(revision 31adfa57ce1ed36312e60622d6a3d0ddcfb98382)
@@ -5,4 +5,5 @@
 from pyramid.i18n import TranslationStringFactory
 from pyramid_simpleform import Form, State
+from pytz import common_timezones
 
 from ..models.user import User
@@ -167,8 +168,11 @@
         # Saved, send the user to the public view of her profile
         return HTTPFound(location=request.resource_url(context, 'profile'))
+
     # prevent crashes on the form
     if 'picture' in form.data:
         del form.data['picture']
-    return {'form': OWFormRenderer(form)}
+
+    return {'form': OWFormRenderer(form),
+            'timezones': common_timezones}
 
 
Index: setup.py
===================================================================
--- setup.py	(revision d507f75fff71fd217d2b42eeb35e65ea22b716ad)
+++ setup.py	(revision 31adfa57ce1ed36312e60622d6a3d0ddcfb98382)
@@ -27,5 +27,6 @@
     'unidecode',
     'gpxpy',
-    'lxml'
+    'lxml',
+    'pytz'
 ]
 
