+ Staff Member #1
+Biography of instructor/staff member #1
+diff --git a/cms/djangoapps/models/settings/course_metadata.py b/cms/djangoapps/models/settings/course_metadata.py
index f186fbf11648..603865b8846b 100644
--- a/cms/djangoapps/models/settings/course_metadata.py
+++ b/cms/djangoapps/models/settings/course_metadata.py
@@ -2,7 +2,6 @@
from contentstore.utils import get_modulestore
from xmodule.modulestore.inheritance import own_metadata
from xblock.fields import Scope
-from xmodule.course_module import CourseDescriptor
from cms.xmodule_namespace import CmsBlockMixin
@@ -20,7 +19,9 @@ class CourseMetadata(object):
'enrollment_end',
'tabs',
'graceperiod',
- 'checklists']
+ 'checklists',
+ 'show_timezone'
+ ]
@classmethod
def fetch(cls, course_location):
diff --git a/common/lib/xmodule/xmodule/course_module.py b/common/lib/xmodule/xmodule/course_module.py
index 658a095d1480..24e6995ae105 100644
--- a/common/lib/xmodule/xmodule/course_module.py
+++ b/common/lib/xmodule/xmodule/course_module.py
@@ -337,7 +337,14 @@ class CourseFields(object):
"action_external": False}]}
])
info_sidebar_name = String(scope=Scope.settings, default='Course Handouts')
- show_timezone = Boolean(help="True if timezones should be shown on dates in the courseware", scope=Scope.settings, default=True)
+ show_timezone = Boolean(
+ help="True if timezones should be shown on dates in the courseware. Deprecated in favor of due_date_display_format.",
+ scope=Scope.settings, default=True
+ )
+ due_date_display_format = String(
+ help="Format supported by strftime for displaying due dates. Takes precedence over show_timezone.",
+ scope=Scope.settings, default=None
+ )
enrollment_domain = String(help="External login method associated with user accounts allowed to register in course",
scope=Scope.settings)
course_image = String(
@@ -391,7 +398,13 @@ def __init__(self, *args, **kwargs):
elif isinstance(self.location, CourseLocator):
self.wiki_slug = self.location.course_id or self.display_name
- msg = None
+ if self.due_date_display_format is None and self.show_timezone is False:
+ # For existing courses with show_timezone set to False (and no due_date_display_format specified),
+ # set the due_date_display_format to what would have been shown previously (with no timezone).
+ # Then remove show_timezone so that if the user clears out the due_date_display_format,
+ # they get the default date display.
+ self.due_date_display_format = u"%b %d, %Y at %H:%M"
+ delattr(self, 'show_timezone')
# NOTE: relies on the modulestore to call set_grading_policy() right after
# init. (Modulestore is in charge of figuring out where to load the policy from)
diff --git a/common/lib/xmodule/xmodule/tests/test_date_utils.py b/common/lib/xmodule/xmodule/tests/test_date_utils.py
index 37f30e1b566d..c5f71dfb56e8 100644
--- a/common/lib/xmodule/xmodule/tests/test_date_utils.py
+++ b/common/lib/xmodule/xmodule/tests/test_date_utils.py
@@ -1,7 +1,7 @@
"""Tests for xmodule.util.date_utils"""
from nose.tools import assert_equals, assert_false # pylint: disable=E0611
-from xmodule.util.date_utils import get_default_time_display, almost_same_datetime
+from xmodule.util.date_utils import get_default_time_display, get_time_display, almost_same_datetime
from datetime import datetime, timedelta, tzinfo
from pytz import UTC
@@ -12,25 +12,34 @@ def test_get_default_time_display():
assert_equals(
"Mar 12, 1992 at 15:03 UTC",
get_default_time_display(test_time))
- assert_equals(
- "Mar 12, 1992 at 15:03 UTC",
- get_default_time_display(test_time, True))
- assert_equals(
- "Mar 12, 1992 at 15:03",
- get_default_time_display(test_time, False))
-def test_get_default_time_display_notz():
+def test_get_dflt_time_disp_notz():
test_time = datetime(1992, 3, 12, 15, 3, 30)
assert_equals(
"Mar 12, 1992 at 15:03 UTC",
get_default_time_display(test_time))
- assert_equals(
- "Mar 12, 1992 at 15:03 UTC",
- get_default_time_display(test_time, True))
- assert_equals(
- "Mar 12, 1992 at 15:03",
- get_default_time_display(test_time, False))
+
+
+def test_get_time_disp_ret_empty():
+ assert_equals("", get_time_display(None))
+ test_time = datetime(1992, 3, 12, 15, 3, 30, tzinfo=UTC)
+ assert_equals("", get_time_display(test_time, ""))
+
+
+def test_get_time_display():
+ test_time = datetime(1992, 3, 12, 15, 3, 30, tzinfo=UTC)
+ assert_equals("dummy text", get_time_display(test_time, 'dummy text'))
+ assert_equals("Mar 12 1992", get_time_display(test_time, '%b %d %Y'))
+ assert_equals("Mar 12 1992 UTC", get_time_display(test_time, '%b %d %Y %Z'))
+ assert_equals("Mar 12 15:03", get_time_display(test_time, '%b %d %H:%M'))
+
+
+def test_get_time_pass_through():
+ test_time = datetime(1992, 3, 12, 15, 3, 30, tzinfo=UTC)
+ assert_equals("Mar 12, 1992 at 15:03 UTC", get_time_display(test_time))
+ assert_equals("Mar 12, 1992 at 15:03 UTC", get_time_display(test_time, None))
+ assert_equals("Mar 12, 1992 at 15:03 UTC", get_time_display(test_time, "%"))
# pylint: disable=W0232
@@ -50,12 +59,6 @@ def test_get_default_time_display_no_tzname():
assert_equals(
"Mar 12, 1992 at 15:03-0300",
get_default_time_display(test_time))
- assert_equals(
- "Mar 12, 1992 at 15:03-0300",
- get_default_time_display(test_time, True))
- assert_equals(
- "Mar 12, 1992 at 15:03",
- get_default_time_display(test_time, False))
def test_almost_same_datetime():
diff --git a/common/lib/xmodule/xmodule/util/date_utils.py b/common/lib/xmodule/xmodule/util/date_utils.py
index 8baa59558b3e..aec4f20788ad 100644
--- a/common/lib/xmodule/xmodule/util/date_utils.py
+++ b/common/lib/xmodule/xmodule/util/date_utils.py
@@ -2,32 +2,46 @@
Convenience methods for working with datetime objects
"""
from datetime import timedelta
-from django.utils.translation import ugettext as _
-def get_default_time_display(dt, show_timezone=True):
+def get_default_time_display(dtime):
"""
Converts a datetime to a string representation. This is the default
representation used in Studio and LMS.
- It is of the form "Apr 09, 2013 at 16:00" or "Apr 09, 2013 at 16:00 UTC",
- depending on the value of show_timezone.
+ It is of the form "Apr 09, 2013 at 16:00 UTC".
If None is passed in for dt, an empty string will be returned.
- The default value of show_timezone is True.
"""
- if dt is None:
+ if dtime is None:
return u""
- timezone = u""
- if show_timezone:
- if dt.tzinfo is not None:
- try:
- timezone = u" " + dt.tzinfo.tzname(dt)
- except NotImplementedError:
- timezone = dt.strftime('%z')
- else:
- timezone = u" UTC"
- return unicode(dt.strftime(u"%b %d, %Y {at} %H:%M{tz}")).format(
- at=_(u"at"), tz=timezone).strip()
+ if dtime.tzinfo is not None:
+ try:
+ timezone = u" " + dtime.tzinfo.tzname(dtime)
+ except NotImplementedError:
+ timezone = dtime.strftime('%z')
+ else:
+ timezone = u" UTC"
+ return unicode(dtime.strftime(u"%b %d, %Y at %H:%M{tz}")).format(
+ tz=timezone).strip()
+
+
+def get_time_display(dtime, format_string=None):
+ """
+ Converts a datetime to a string representation.
+
+ If None is passed in for dt, an empty string will be returned.
+
+ If the format_string is None, or if format_string is improperly
+ formatted, this method will return the value from `get_default_time_display`.
+
+ format_string should be a unicode string that is a valid argument for datetime's strftime method.
+ """
+ if dtime is None or format_string is None:
+ return get_default_time_display(dtime)
+ try:
+ return unicode(dtime.strftime(format_string))
+ except ValueError:
+ return get_default_time_display(dtime)
def almost_same_datetime(dt1, dt2, allowed_delta=timedelta(minutes=1)):
diff --git a/common/test/data/due_date/about/overview.html b/common/test/data/due_date/about/overview.html
new file mode 100644
index 000000000000..961786b8f407
--- /dev/null
+++ b/common/test/data/due_date/about/overview.html
@@ -0,0 +1,47 @@
+ Include your long course description here. The long course description should contain 150-400 words. This is paragraph 2 of the long course description. Add more paragraphs as needed. Make sure to enclose them in paragraph tags. Add information about course prerequisites here. Biography of instructor/staff member #1 Biography of instructor/staff member #2 No, a free online version of Chemistry: Principles, Patterns, and Applications, First Edition by Bruce Averill and Patricia Eldredge will be available, though you can purchase a printed version (published by FlatWorld Knowledge) if you’d like. Your answer would be displayed here.
+A multiple choice problem presents radio buttons for student
+input. Students can only select a single option presented. Multiple Choice questions have been the subject of many areas of research due to the early invention and adoption of bubble sheets. One of the main elements that goes into a good multiple choice question is the existence of good distractors. That is, each of the alternate responses presented to the student should be the result of a plausible mistake that a student might make.
+ What Apple device competed with the portable CD player? Explanation The release of the iPod allowed consumers to carry their entire music library with them in a format that did not rely on fragile and energy-intensive spinning disks. About This Course
+ Prerequisites
+ Course Staff
+
+ Staff Member #1
+
+ Staff Member #2
+ Frequently Asked Questions
+ Do I need to buy a textbook?
+ Question #2
+