浏览代码

Merge branch '118/dev/v1.0_beta/user_timezone' of https://github.com/buxx/tracim into buxx-118/dev/v1.0_beta/user_timezone

Bastien Sevajol (Algoo) 8 年前
父节点
当前提交
aff69a9353

+ 26 - 0
tracim/migration/versions/2cd20ff3d23a_user_timezone.py 查看文件

1
+"""user_timezone
2
+
3
+Revision ID: 2cd20ff3d23a
4
+Revises: b4b8d57b54e5
5
+Create Date: 2016-11-08 11:32:00.903232
6
+
7
+"""
8
+
9
+# revision identifiers, used by Alembic.
10
+revision = '2cd20ff3d23a'
11
+down_revision = 'b4b8d57b54e5'
12
+
13
+from alembic import op
14
+import sqlalchemy as sa
15
+
16
+
17
+def upgrade():
18
+    ### commands auto generated by Alembic - please adjust! ###
19
+    op.add_column('users', sa.Column('timezone', sa.Unicode(length=255), server_default='', nullable=False))
20
+    ### end Alembic commands ###
21
+
22
+
23
+def downgrade():
24
+    ### commands auto generated by Alembic - please adjust! ###
25
+    op.drop_column('users', 'timezone')
26
+    ### end Alembic commands ###

+ 9 - 3
tracim/tracim/controllers/user.py 查看文件

1
 # -*- coding: utf-8 -*-
1
 # -*- coding: utf-8 -*-
2
+import pytz
2
 from webob.exc import HTTPForbidden
3
 from webob.exc import HTTPForbidden
3
 import tg
4
 import tg
4
 from tg import tmpl_context
5
 from tg import tmpl_context
157
 
158
 
158
         dictified_user = Context(CTX.USER).toDict(current_user, 'user')
159
         dictified_user = Context(CTX.USER).toDict(current_user, 'user')
159
         fake_api = DictLikeClass(next_url=next_url)
160
         fake_api = DictLikeClass(next_url=next_url)
160
-        return DictLikeClass(result=dictified_user, fake_api=fake_api)
161
+        return DictLikeClass(
162
+            result=dictified_user,
163
+            fake_api=fake_api,
164
+            timezones=pytz.all_timezones,
165
+        )
161
 
166
 
162
     @tg.expose('tracim.templates.workspace.edit')
167
     @tg.expose('tracim.templates.workspace.edit')
163
-    def put(self, user_id, name, email, next_url=None):
168
+    def put(self, user_id, name, email, timezone, next_url=None):
164
         user_id = tmpl_context.current_user.user_id
169
         user_id = tmpl_context.current_user.user_id
165
         current_user = tmpl_context.current_user
170
         current_user = tmpl_context.current_user
166
         assert user_id==current_user.user_id
171
         assert user_id==current_user.user_id
168
         # Only keep allowed field update
173
         # Only keep allowed field update
169
         updated_fields = self._clean_update_fields({
174
         updated_fields = self._clean_update_fields({
170
             'name': name,
175
             'name': name,
171
-            'email': email
176
+            'email': email,
177
+            'timezone': timezone,
172
         })
178
         })
173
 
179
 
174
         api = UserApi(tmpl_context.current_user)
180
         api = UserApi(tmpl_context.current_user)

二进制
tracim/tracim/i18n/fr/LC_MESSAGES/tracim.mo 查看文件


文件差异内容过多而无法显示
+ 509 - 356
tracim/tracim/i18n/fr/LC_MESSAGES/tracim.po


+ 0 - 1
tracim/tracim/lib/app_globals.py 查看文件

23
         pass
23
         pass
24
 
24
 
25
     VERSION_NUMBER = '1.0.3'
25
     VERSION_NUMBER = '1.0.3'
26
-    LONG_DATE_FORMAT = '%A, the %d of %B %Y at %H:%M'
27
     SHORT_DATE_FORMAT = l_('%B %d at %I:%M%p')
26
     SHORT_DATE_FORMAT = l_('%B %d at %I:%M%p')
28
 
27
 
29
 
28
 

+ 37 - 13
tracim/tracim/lib/helpers.py 查看文件

6
 
6
 
7
 import datetime
7
 import datetime
8
 
8
 
9
+import pytz
9
 import slugify
10
 import slugify
10
-from babel.dates import format_date, format_time
11
+from babel.dates import format_date
12
+from babel.dates import format_time
11
 from markupsafe import Markup
13
 from markupsafe import Markup
12
 
14
 
13
 import tg
15
 import tg
16
+from tg import tmpl_context
14
 from tg.i18n import ugettext as _
17
 from tg.i18n import ugettext as _
15
 
18
 
16
 from tracim.lib import app_globals as plag
19
 from tracim.lib import app_globals as plag
20
 from tracim.lib.content import ContentApi
23
 from tracim.lib.content import ContentApi
21
 from tracim.lib.userworkspace import RoleApi
24
 from tracim.lib.userworkspace import RoleApi
22
 from tracim.lib.workspace import WorkspaceApi
25
 from tracim.lib.workspace import WorkspaceApi
23
-from tracim.model import User
24
 
26
 
25
 from tracim.model.data import ContentStatus
27
 from tracim.model.data import ContentStatus
26
 from tracim.model.data import Content
28
 from tracim.model.data import Content
28
 from tracim.model.data import UserRoleInWorkspace
30
 from tracim.model.data import UserRoleInWorkspace
29
 from tracim.model.data import Workspace
31
 from tracim.model.data import Workspace
30
 
32
 
33
+
34
+def get_with_timezone(
35
+        datetime_object: datetime.datetime,
36
+        to_timezone: str='',
37
+        default_from_timezone: str='UTC',
38
+) -> datetime.datetime:
39
+    """
40
+    Change timezone of a date
41
+    :param datetime_object: datetime to update
42
+    :param to_timezone: timezone name, if equal to '',
43
+    try to grap current user timezone. If no given timezone name and no
44
+    current user timezone, return original date time
45
+    :param default_from_timezone: datetime original timezone if datetime
46
+    object is naive
47
+    :return: datetime updated
48
+    """
49
+    # If no to_timezone, try to grab from current user
50
+    if not to_timezone and tmpl_context.current_user:
51
+        to_timezone = tmpl_context.current_user.timezone
52
+
53
+    # If no to_timezone, return original datetime
54
+    if not to_timezone:
55
+        return datetime_object
56
+
57
+    # If datetime_object have not timezone, set new from default_from_timezone
58
+    if not datetime_object.tzinfo:
59
+        from_tzinfo = pytz.timezone(default_from_timezone)
60
+        datetime_object = from_tzinfo.localize(datetime_object)
61
+
62
+    new_tzinfo = pytz.timezone(to_timezone)
63
+    return datetime_object.astimezone(new_tzinfo)
64
+
65
+
31
 def date_time_in_long_format(datetime_object, format=''):
66
 def date_time_in_long_format(datetime_object, format=''):
32
 
67
 
33
     current_locale = tg.i18n.get_lang()[0]
68
     current_locale = tg.i18n.get_lang()[0]
63
   now = datetime.datetime.now()
98
   now = datetime.datetime.now()
64
   return now.strftime('%Y')
99
   return now.strftime('%Y')
65
 
100
 
66
-def formatLongDateAndTime(datetime_object, format=''):
67
-    """ OBSOLETE
68
-    :param datetime_object:
69
-    :param format:
70
-    :return:
71
-    """
72
-    if not format:
73
-        format = plag.Globals.LONG_DATE_FORMAT
74
-    return datetime_object.strftime(format)
75
-
76
-
77
 
101
 
78
 def icon(icon_name, white=False):
102
 def icon(icon_name, white=False):
79
     if (white):
103
     if (white):

+ 10 - 1
tracim/tracim/lib/user.py 查看文件

31
     def get_one_by_id(self, id: int) -> User:
31
     def get_one_by_id(self, id: int) -> User:
32
         return self._base_query().filter(User.user_id==id).one()
32
         return self._base_query().filter(User.user_id==id).one()
33
 
33
 
34
-    def update(self, user: User, name: str=None, email: str=None, do_save=True):
34
+    def update(
35
+            self,
36
+            user: User,
37
+            name: str=None,
38
+            email: str=None,
39
+            do_save=True,
40
+            timezone: str='',
41
+    ):
35
         if name is not None:
42
         if name is not None:
36
             user.display_name = name
43
             user.display_name = name
37
 
44
 
38
         if email is not None:
45
         if email is not None:
39
             user.email = email
46
             user.email = email
40
 
47
 
48
+        user.timezone = timezone
49
+
41
         if do_save:
50
         if do_save:
42
             self.save(user)
51
             self.save(user)
43
 
52
 

+ 1 - 0
tracim/tracim/model/auth.py 查看文件

124
     created = Column(DateTime, default=datetime.utcnow)
124
     created = Column(DateTime, default=datetime.utcnow)
125
     is_active = Column(Boolean, default=True, nullable=False)
125
     is_active = Column(Boolean, default=True, nullable=False)
126
     imported_from = Column(Unicode(32), nullable=True)
126
     imported_from = Column(Unicode(32), nullable=True)
127
+    timezone = Column(Unicode(255), nullable=False, server_default='')
127
     _webdav_left_digest_response_hash = Column('webdav_left_digest_response_hash', Unicode(128))
128
     _webdav_left_digest_response_hash = Column('webdav_left_digest_response_hash', Unicode(128))
128
     auth_token = Column(Unicode(255))
129
     auth_token = Column(Unicode(255))
129
     auth_token_created = Column(DateTime)
130
     auth_token_created = Column(DateTime)

+ 2 - 0
tracim/tracim/model/serializers.py 查看文件

860
     result['enabled'] = user.is_active
860
     result['enabled'] = user.is_active
861
     result['profile'] = user.profile
861
     result['profile'] = user.profile
862
     result['has_password'] = user.password!=None
862
     result['has_password'] = user.password!=None
863
+    result['timezone'] = user.timezone
863
     return result
864
     return result
864
 
865
 
865
 
866
 
882
     result['enabled'] = user.is_active
883
     result['enabled'] = user.is_active
883
     result['profile'] = user.profile
884
     result['profile'] = user.profile
884
     result['calendar_url'] = user.calendar_url
885
     result['calendar_url'] = user.calendar_url
886
+    result['timezone'] = user.timezone
885
 
887
 
886
     return result
888
     return result
887
 
889
 

+ 2 - 3
tracim/tracim/templates/admin/workspace_getone.mak 查看文件

24
 <%def name="TITLE_ROW()">
24
 <%def name="TITLE_ROW()">
25
     <div class="row-fluid">
25
     <div class="row-fluid">
26
         <div>
26
         <div>
27
-            <%
28
-                subtitle = _('created on {}').format(h.formatLongDateAndTime(result.workspace.created))
29
-            %>
27
+            <% created_localized = h.get_with_timezone(result.workspace.created) %>
28
+            <% subtitle = _('workspace created on {date} at {time}').format(date=h.date(created_localized), time=h.time(created_localized)) %>
30
             ${ROW.TITLE_ROW(_('Workspace {}').format(result.workspace.label), 'fa-bank', 'col-md-offset-3 col-md-7', 't-user-color', subtitle)}
29
             ${ROW.TITLE_ROW(_('Workspace {}').format(result.workspace.label), 'fa-bank', 'col-md-offset-3 col-md-7', 't-user-color', subtitle)}
31
         </div>
30
         </div>
32
     </div>
31
     </div>

+ 4 - 2
tracim/tracim/templates/file/getone.mak 查看文件

48
         </h1>
48
         </h1>
49
 
49
 
50
         <div style="margin: -1.5em auto -1.5em auto;" class="tracim-less-visible">
50
         <div style="margin: -1.5em auto -1.5em auto;" class="tracim-less-visible">
51
-          <p>${_('file created on {date} at {time} by <b>{author}</b>').format(date=h.date(result.file.created), time=h.time(result.file.created), author=result.file.owner.name)|n}</p>
51
+            <% created_localized = h.get_with_timezone(result.file.created) %>
52
+          <p>${_('file created on {date} at {time} by <b>{author}</b>').format(date=h.date(created_localized), time=h.time(created_localized), author=result.file.owner.name)|n}</p>
52
         </div>
53
         </div>
53
     </div>
54
     </div>
54
 </div>
55
 </div>
107
                 </tr>
108
                 </tr>
108
                 <tr>
109
                 <tr>
109
                     <td class="tracim-title">${_('Modified')}</td>
110
                     <td class="tracim-title">${_('Modified')}</td>
110
-                    <td>${h.format_short(result.file.created)|n} ${_('by {}').format(result.file.owner.name)}</td>
111
+                    <% created_localized = h.get_with_timezone(result.file.created) %>
112
+                    <td>${h.format_short(created_localized)|n} ${_('by {}').format(result.file.owner.name)}</td>
111
                 </tr>
113
                 </tr>
112
             </table>
114
             </table>
113
         </div>
115
         </div>

+ 2 - 1
tracim/tracim/templates/folder/getone.mak 查看文件

46
         </h1>
46
         </h1>
47
 
47
 
48
         <div style="margin: -1.5em auto -1.5em auto;" class="tracim-less-visible">
48
         <div style="margin: -1.5em auto -1.5em auto;" class="tracim-less-visible">
49
-          <p>${_('folder created on {date} at {time} by <b>{author}</b>').format(date=h.date(result.folder.created), time=h.time(result.folder.created), author=result.folder.owner.name)|n}</p>
49
+            <% created_localized = h.get_with_timezone(result.folder.created) %>
50
+          <p>${_('folder created on {date} at {time} by <b>{author}</b>').format(date=h.date(created_localized), time=h.time(created_localized), author=result.folder.owner.name)|n}</p>
50
         </div>
51
         </div>
51
     </div>
52
     </div>
52
 </div>
53
 </div>

+ 2 - 1
tracim/tracim/templates/page/getone.mak 查看文件

47
         </h1>
47
         </h1>
48
 
48
 
49
         <div style="margin: -1.5em auto -1.5em auto;" class="tracim-less-visible">
49
         <div style="margin: -1.5em auto -1.5em auto;" class="tracim-less-visible">
50
-          <p>${_('page created on {date} at {time} by <b>{author}</b>').format(date=h.date(result.page.created), time=h.time(result.page.created), author=result.page.owner.name)|n}</p>
50
+            <% created_localized = h.get_with_timezone(result.page.created) %>
51
+          <p>${_('page created on {date} at {time} by <b>{author}</b>').format(date=h.date(created_localized), time=h.time(created_localized), author=result.page.owner.name)|n}</p>
51
         </div>
52
         </div>
52
     </div>
53
     </div>
53
 </div>
54
 </div>

+ 2 - 1
tracim/tracim/templates/search/display.mak 查看文件

42
         </h1>
42
         </h1>
43
 
43
 
44
         <div style="margin: -1.5em auto -1.5em auto;" class="tracim-less-visible">
44
         <div style="margin: -1.5em auto -1.5em auto;" class="tracim-less-visible">
45
-##          <p>${_('folder created on {date} at {time} by <b>{author}</b>').format(date=h.date(result.folder.created), time=h.time(result.folder.created), author=result.folder.owner.name)|n}</p>
45
+            <% created_localized = h.get_with_timezone(result.folder.created) %>
46
+##          <p>${_('folder created on {date} at {time} by <b>{author}</b>').format(date=h.date(created_localized), time=h.time(created_localized), author=result.folder.owner.name)|n}</p>
46
         </div>
47
         </div>
47
     </div>
48
     </div>
48
 </div>
49
 </div>

+ 2 - 1
tracim/tracim/templates/thread/getone.mak 查看文件

48
         </h1>
48
         </h1>
49
 
49
 
50
         <div style="margin: -1.5em auto -1.5em auto;" class="tracim-less-visible">
50
         <div style="margin: -1.5em auto -1.5em auto;" class="tracim-less-visible">
51
-          <p>${_('page created on {date} at {time} by <b>{author}</b>').format(date=h.date(result.thread.created), time=h.time(result.thread.created), author=result.thread.owner.name)|n}</p>
51
+            <% created_localized = h.get_with_timezone(result.thread.created) %>
52
+          <p>${_('page created on {date} at {time} by <b>{author}</b>').format(date=h.date(created_localized), time=h.time(created_localized), author=result.thread.owner.name)|n}</p>
52
         </div>
53
         </div>
53
     </div>
54
     </div>
54
 </div>
55
 </div>

+ 14 - 0
tracim/tracim/templates/user_workspace_forms.mak 查看文件

115
                 <span class="info readonly">${_('This calendar URL will work with CalDav compatibles clients')}</span>
115
                 <span class="info readonly">${_('This calendar URL will work with CalDav compatibles clients')}</span>
116
                 <input id="calendar" type="text" class="form-control"  disabled="disabled" value="${user.calendar_url}" />
116
                 <input id="calendar" type="text" class="form-control"  disabled="disabled" value="${user.calendar_url}" />
117
             </div>
117
             </div>
118
+            <div class="form-group">
119
+                <label for="timezone">${_('Timezone')}</label>
120
+                <span class="info readonly">${_('Dates will be displayed with this timezone')}</span>
121
+                <select id="timezone" name="timezone" class="form-control">
122
+                    <option value=""></option>
123
+                    % for timezone in timezones:
124
+                        % if timezone == user.timezone:
125
+                            <option value="${timezone}" selected>${timezone}</option>
126
+                        % else:
127
+                            <option value="${timezone}">${timezone}</option>
128
+                        % endif
129
+                    % endfor
130
+                </select>
131
+            </div>
118
         </div>
132
         </div>
119
         <div class="modal-footer">
133
         <div class="modal-footer">
120
             <span class="pull-right t-modal-form-submit-button">
134
             <span class="pull-right t-modal-form-submit-button">

+ 6 - 3
tracim/tracim/templates/user_workspace_widgets.mak 查看文件

303
 </%def>
303
 </%def>
304
 
304
 
305
 <%def name="SECURED_TIMELINE_ITEM(user, item)">
305
 <%def name="SECURED_TIMELINE_ITEM(user, item)">
306
+##     <% created_localized = h.get_with_timezone(item.created) %>
306
 ##     <div class="row t-odd-or-even t-hacky-thread-comment-border-top">
307
 ##     <div class="row t-odd-or-even t-hacky-thread-comment-border-top">
307
 ##         <div class="col-sm-7 col-sm-offset-3">
308
 ##         <div class="col-sm-7 col-sm-offset-3">
308
 ##             <div class="t-timeline-item">
309
 ##             <div class="t-timeline-item">
312
 ##                 <h5 style="margin: 0;">
313
 ##                 <h5 style="margin: 0;">
313
 ##                     <span class="tracim-less-visible">${_('<strong>{}</strong> wrote:').format(item.owner.name)|n}</span>
314
 ##                     <span class="tracim-less-visible">${_('<strong>{}</strong> wrote:').format(item.owner.name)|n}</span>
314
 ##
315
 ##
315
-##                     <div class="pull-right text-right t-timeline-item-moment" title="${h.date_time(item.created)|n}">
316
+##                     <div class="pull-right text-right t-timeline-item-moment" title="${h.date_time(created_localized)|n}">
316
 ##                         ${_('{delta} ago').format(delta=item.created_as_delta)}
317
 ##                         ${_('{delta} ago').format(delta=item.created_as_delta)}
317
 ##
318
 ##
318
 ##                         % if h.is_item_still_editable(item) and item.owner.id==user.id:
319
 ##                         % if h.is_item_still_editable(item) and item.owner.id==user.id:
336
 </%def>
337
 </%def>
337
 
338
 
338
 <%def name="SECURED_HISTORY_VIRTUAL_EVENT(user, event)">
339
 <%def name="SECURED_HISTORY_VIRTUAL_EVENT(user, event)">
340
+    <% created_localized = h.get_with_timezone(event.created) %>
339
     <% is_new_css_class = 't-is-new-content' if event.is_new else '' %>
341
     <% is_new_css_class = 't-is-new-content' if event.is_new else '' %>
340
 
342
 
341
     <div class="row t-odd-or-even t-hacky-thread-comment-border-top ${is_new_css_class}">
343
     <div class="row t-odd-or-even t-hacky-thread-comment-border-top ${is_new_css_class}">
353
                         <span class="tracim-less-visible">${_('{} by <strong>{}</strong>').format(event.label, event.owner.name)|n}</span>
355
                         <span class="tracim-less-visible">${_('{} by <strong>{}</strong>').format(event.label, event.owner.name)|n}</span>
354
                     % endif
356
                     % endif
355
 
357
 
356
-                    <div class="pull-right text-right t-timeline-item-moment" title="${h.date_time(event.created)|n}">
358
+                    <div class="pull-right text-right t-timeline-item-moment" title="${h.date_time(created_localized)|n}">
357
                         ${_('{delta} ago').format(delta=event.created_as_delta)}
359
                         ${_('{delta} ago').format(delta=event.created_as_delta)}
358
 
360
 
359
                         % if h.is_item_still_editable(CFG, event) and event.owner.id==user.id:
361
                         % if h.is_item_still_editable(CFG, event) and event.owner.id==user.id:
374
 </%def>
376
 </%def>
375
 
377
 
376
 <%def name="SECURED_HISTORY_VIRTUAL_EVENT_AS_TABLE_ROW(user, event, current_revision_id)">
378
 <%def name="SECURED_HISTORY_VIRTUAL_EVENT_AS_TABLE_ROW(user, event, current_revision_id)">
379
+    <% created_localized = h.get_with_timezone(event.created) %>
377
     <%
380
     <%
378
         warning_or_not = ('', 'warning')[current_revision_id==event.id]
381
         warning_or_not = ('', 'warning')[current_revision_id==event.id]
379
         row_css = 't-is-new-content' if event.is_new else warning_or_not
382
         row_css = 't-is-new-content' if event.is_new else warning_or_not
382
         <td class="t-less-visible">
385
         <td class="t-less-visible">
383
             <span class="label label-default">${ICON.FA_FW(event.type.icon)} ${event.type.label}</span>
386
             <span class="label label-default">${ICON.FA_FW(event.type.icon)} ${event.type.label}</span>
384
         </td>
387
         </td>
385
-        <td title="${h.date_time(event.created)|n}">${_('{delta} ago').format(delta=event.created_as_delta)}</td>
388
+        <td title="${h.date_time(created_localized)|n}">${_('{delta} ago').format(delta=event.created_as_delta)}</td>
386
         <td>${event.owner.name}</td>
389
         <td>${event.owner.name}</td>
387
 ## FIXME - REMOVE                            <td>${event}</td>
390
 ## FIXME - REMOVE                            <td>${event}</td>
388
 
391
 

+ 2 - 1
tracim/tracim/templates/workspace/getone.mak 查看文件

44
         </h1>
44
         </h1>
45
 
45
 
46
         <div style="margin: -1.5em auto -1.5em auto;" class="t-less-visible">
46
         <div style="margin: -1.5em auto -1.5em auto;" class="t-less-visible">
47
-          <p>${_('workspace created on {date} at {time}').format(date=h.date(result.workspace.created), time=h.time(result.workspace.created))|n}</p>
47
+            <% created_localized = h.get_with_timezone(result.workspace.created) %>
48
+          <p>${_('workspace created on {date} at {time}').format(date=h.date(created_localized), time=h.time(created_localized))|n}</p>
48
         </div>
49
         </div>
49
     </div>
50
     </div>
50
 </div>
51
 </div>

+ 2 - 1
tracim/tracim/tests/__init__.py 查看文件

51
         try:
51
         try:
52
             super()._check_status(status, res)
52
             super()._check_status(status, res)
53
         except AppError as exc:
53
         except AppError as exc:
54
-            dump_file_path = "/tmp/debug_%d_%s.html" % (time.time() * 1000, res.request.path_qs[1:])
54
+            escaped_page_name = res.request.path_qs[1:].replace('/', '')
55
+            dump_file_path = "/tmp/debug_%d_%s.html" % (time.time() * 1000, escaped_page_name)
55
             if os.path.exists("/tmp"):
56
             if os.path.exists("/tmp"):
56
                 with open(dump_file_path, 'w') as dump_file:
57
                 with open(dump_file_path, 'w') as dump_file:
57
                     print(res.ubody, file=dump_file)
58
                     print(res.ubody, file=dump_file)

+ 1 - 0
tracim/tracim/tests/functional/test_ldap_restrictions.py 查看文件

68
             OrderedDict([
68
             OrderedDict([
69
                 ('name', 'Lawrence Lessig YEAH'),
69
                 ('name', 'Lawrence Lessig YEAH'),
70
                 ('email', 'An-other-email@fsf.org'),
70
                 ('email', 'An-other-email@fsf.org'),
71
+                ('timezone', ''),
71
             ])
72
             ])
72
         )
73
         )
73
 
74
 

+ 21 - 8
tracim/tracim/tests/library/test_helpers.py 查看文件

1
 # -*- coding: utf-8 -*-
1
 # -*- coding: utf-8 -*-
2
 
2
 
3
 import datetime
3
 import datetime
4
+from unittest.mock import MagicMock
4
 
5
 
6
+import pytz
7
+from babel.dates import get_timezone
5
 from nose.tools import eq_
8
 from nose.tools import eq_
6
-from nose.tools import ok_
9
+from tg.request_local import TurboGearsContextMember
10
+from tg.util.webtest import test_context
11
+from tg import tmpl_context
7
 
12
 
8
 import tracim.lib.helpers as h
13
 import tracim.lib.helpers as h
9
 from tracim.config.app_cfg import CFG
14
 from tracim.config.app_cfg import CFG
10
-from tracim.model.data import Content
11
-from tracim.model.data import ContentType
12
-from tracim.model.data import Workspace
13
-
14
-from tracim.model.serializers import Context
15
-from tracim.model.serializers import CTX
16
 from tracim.model.serializers import DictLikeClass
15
 from tracim.model.serializers import DictLikeClass
17
-
18
 from tracim.tests import TestStandard
16
 from tracim.tests import TestStandard
19
 
17
 
20
 
18
 
45
         config.DATA_UPDATE_ALLOWED_DURATION = 8
43
         config.DATA_UPDATE_ALLOWED_DURATION = 8
46
         item.created = datetime.datetime.now() - datetime.timedelta(0, 10)
44
         item.created = datetime.datetime.now() - datetime.timedelta(0, 10)
47
         eq_(False, h.is_item_still_editable(config, item))
45
         eq_(False, h.is_item_still_editable(config, item))
46
+
47
+    def test_unit__change_datetime_timezone__ok__with_naive_and_current_user(self):  # nopep8
48
+        user_mock = MagicMock(timezone='America/Guadeloupe')
49
+
50
+        with test_context(self.app):
51
+            tmpl_context.current_user = user_mock
52
+            naive_datetime = datetime.datetime(2000, 1, 1, 0, 0, 0)
53
+
54
+            new_datetime = h.get_with_timezone(
55
+                datetime_object=naive_datetime,
56
+                default_from_timezone='UTC',
57
+                to_timezone='',  # user_mock.timezone should be used
58
+            )
59
+
60
+            eq_(str(new_datetime), '1999-12-31 20:00:00-04:00')