~azzar1/unity/add-show-desktop-key

« back to all changes in this revision

Viewing changes to ivle/date.py

Quick port of fileservice to the new framework. It's still very much old-style,
though.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
# along with this program; if not, write to the Free Software
16
16
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
17
 
18
 
'''Utilities for making nice, human readable dates.'''
 
18
# Module: Date utilities
 
19
# Author: William Grant
 
20
# Date: 16/07/2008
19
21
 
20
22
import time
21
 
import datetime
22
 
 
23
 
def get_datetime(datetime_or_seconds):
24
 
    '''Return the given datetime, or convert the given seconds since epoch.
25
 
 
26
 
    >>> get_datetime(1000000000)
27
 
    datetime.datetime(2001, 9, 9, 11, 46, 40)
28
 
    >>> get_datetime(2000000000)
29
 
    datetime.datetime(2033, 5, 18, 13, 33, 20)
30
 
 
31
 
    >>> get_datetime(datetime.datetime(2009, 5, 26, 11, 38, 53))
32
 
    datetime.datetime(2009, 5, 26, 11, 38, 53)
33
 
    >>> get_datetime(datetime.datetime(2001, 9, 9, 11, 46, 40))
34
 
    datetime.datetime(2001, 9, 9, 11, 46, 40)
35
 
    '''
36
 
    if type(datetime_or_seconds) is datetime.datetime:
37
 
        return datetime_or_seconds
38
 
    return datetime.datetime.fromtimestamp(datetime_or_seconds)
39
 
 
40
 
def make_date_nice(datetime_or_seconds):
41
 
    """Generate a full human-readable representation of a date and time.
42
 
 
43
 
    Given a datetime or number of seconds elapsed since the epoch,
 
23
 
 
24
seconds_per_day = 86400 # 60 * 60 * 24
 
25
if time.daylight:
 
26
    timezone_offset = time.altzone
 
27
else:
 
28
    timezone_offset = time.timezone
 
29
 
 
30
def make_date_nice(seconds_since_epoch):
 
31
    """Given a number of seconds elapsed since the epoch,
44
32
    generates a string representing the date/time in human-readable form.
45
33
    "ddd mmm dd, yyyy h:m a"
46
 
 
47
 
    >>> make_date_nice(datetime.datetime(2009, 5, 26, 11, 38, 53))
48
 
    'Tue May 26 2009, 11:38am'
49
34
    """
50
 
    dt = get_datetime(datetime_or_seconds)
51
 
    return dt.strftime("%a %b %d %Y, %l:%M%P")
52
 
 
53
 
def make_date_nice_short(datetime_or_seconds):
54
 
    """Generate a very compact human-readable representation of a date.
55
 
 
56
 
    Given a datetime or number of seconds elapsed since the epoch,
 
35
    #return time.ctime(seconds_since_epoch)
 
36
    return time.strftime("%a %b %d %Y, %I:%M %p",
 
37
        time.localtime(seconds_since_epoch))
 
38
 
 
39
def make_date_nice_short(seconds_since_epoch):
 
40
    """Given a number of seconds elapsed since the epoch,
57
41
    generates a string representing the date in human-readable form.
58
42
    Does not include the time.
59
 
 
60
 
    >>> now = datetime.datetime.now()
61
 
    >>> make_date_nice_short(now)
62
 
    'Today'
63
 
    >>> make_date_nice_short(now - datetime.timedelta(1))
64
 
    'Yesterday'
65
 
    >>> make_date_nice_short(now - datetime.timedelta(2))
66
 
    '2 days ago'
67
 
    >>> make_date_nice_short(now - datetime.timedelta(5))
68
 
    '5 days ago'
69
 
    >>> make_date_nice_short(1242783748)
70
 
    'May 20, 2009'
71
 
    """
72
 
 
73
 
    dt = get_datetime(datetime_or_seconds)
74
 
    now = datetime.datetime.now()
75
 
 
 
43
    This function generates a very compact representation."""
76
44
    # Use a "naturalisation" algorithm.
77
 
    delta = now - dt
78
 
 
79
 
    if delta.days <= 5:
 
45
    days_ago = (int(time.time() - timezone_offset) / seconds_per_day
 
46
        - int(seconds_since_epoch - timezone_offset) / seconds_per_day)
 
47
    if days_ago <= 5:
80
48
        # Dates today or yesterday, return "today" or "yesterday".
81
 
        if delta.days == 0:
 
49
        if days_ago == 0:
82
50
            return "Today"
83
 
        elif delta.days == 1:
 
51
        elif days_ago == 1:
84
52
            return "Yesterday"
85
53
        else:
86
 
            # Dates in the last 5 days, return "n days ago".
87
 
            return str(delta.days) + " days ago"
 
54
            return str(days_ago) + " days ago"
 
55
        # Dates in the last 5 days, return "n days ago".
88
56
    # Other dates, return a short date format.
89
57
    # If within the same year, omit the year (mmm dd)
90
 
    if dt.year == now.year:
91
 
        return dt.strftime("%b %d")
 
58
    if time.localtime(seconds_since_epoch).tm_year==time.localtime().tm_year:
 
59
        return time.strftime("%b %d", time.localtime(seconds_since_epoch))
92
60
    # Else, include the year (mmm dd, yyyy)
93
61
    else:
94
 
        return dt.strftime("%b %d, %Y")
95
 
 
96
 
def format_datetime_for_paragraph(datetime_or_seconds):
97
 
    """Generate a compact representation of a datetime for use in a paragraph.
98
 
 
99
 
    Given a datetime or number of seconds elapsed since the epoch, generates
100
 
    a compact string representing the date and time in human-readable form.
101
 
 
102
 
    Unlike make_date_nice_short, the time will always be included.
103
 
 
104
 
    Also unlike make_date_nice_short, it is suitable for use in the middle of
105
 
    a block of prose and properly handles timestamps in the future nicely.
106
 
 
107
 
    >>> now = datetime.datetime.now()
108
 
    >>> today = now.date()
109
 
    >>> time = datetime.time(10, 35, 40)
110
 
    >>> earlier = datetime.datetime.combine(today, time)
111
 
    >>> date = datetime.datetime(2009, 5, 20, 21, 19, 53)
112
 
 
113
 
    >>> format_datetime_for_paragraph(now)
114
 
    'now'
115
 
 
116
 
    # We can go backwards and forwards a little while and be pretty.
117
 
    >>> format_datetime_for_paragraph(now - datetime.timedelta(0, 40))
118
 
    '40 seconds ago'
119
 
    >>> format_datetime_for_paragraph(now + datetime.timedelta(0, 30))
120
 
    'in 29 seconds'
121
 
 
122
 
    >>> format_datetime_for_paragraph(now - datetime.timedelta(0, 245))
123
 
    '4 minutes ago'
124
 
    >>> format_datetime_for_paragraph(now + datetime.timedelta(0, 3500))
125
 
    'in 58 minutes'
126
 
 
127
 
    # If we go back further, it gets a bit ugly.
128
 
    >>> format_datetime_for_paragraph(earlier - datetime.timedelta(1))
129
 
    'yesterday at 10:35am'
130
 
    >>> format_datetime_for_paragraph(date)
131
 
    'on 2009-05-20 at  9:19pm'
132
 
 
133
 
    >>> format_datetime_for_paragraph(earlier + datetime.timedelta(1))
134
 
    'tomorrow at 10:35am'
135
 
    """
136
 
 
137
 
    dt = get_datetime(datetime_or_seconds)
138
 
    now = datetime.datetime.now()
139
 
 
140
 
    delta = dt - now
141
 
 
142
 
    # If the date is earlier than now, we want to either say something like
143
 
    # '5 days ago' or '25 seconds ago', 'yesterday at 08:54' or
144
 
    # 'on 2009-03-26 at 20:09'.
145
 
 
146
 
    # If the time is within one hour of now, we show it nicely in either
147
 
    # minutes or seconds.
148
 
 
149
 
    if abs(delta).days == 0 and abs(delta).seconds <= 1:
150
 
        return 'now'
151
 
 
152
 
    if abs(delta).days == 0 and abs(delta).seconds < 60*60:
153
 
        if abs(delta) == delta:
154
 
            # It's in the future.
155
 
            prefix = 'in '
156
 
            suffix = ''
157
 
        else:
158
 
            prefix = ''
159
 
            suffix = ' ago'
160
 
 
161
 
        # Show the number of minutes unless we are within two minutes.
162
 
        if abs(delta).seconds >= 120:
163
 
            return (prefix + '%d minutes' + suffix) % (abs(delta).seconds / 60)
164
 
        else:
165
 
            return (prefix + '%d seconds' + suffix) % (abs(delta).seconds)
166
 
 
167
 
    if dt < now:
168
 
        if dt.date() == now.date():
169
 
            # Today.
170
 
            return dt.strftime('today at %l:%M%P')
171
 
        elif dt.date() == now.date() - datetime.timedelta(days=1):
172
 
            # Yesterday.
173
 
            return dt.strftime('yesterday at %l:%M%P')
174
 
    elif dt > now:
175
 
        if dt.date() == now.date():
176
 
            # Today.
177
 
            return dt.strftime('today at %l:%M%P')
178
 
        elif dt.date() == now.date() + datetime.timedelta(days=1):
179
 
            # Tomorrow
180
 
            return dt.strftime('tomorrow at %l:%M%P')
181
 
 
182
 
    return dt.strftime('on %Y-%m-%d at %l:%M%P')
 
62
        return time.strftime("%b %d, %Y", time.localtime(seconds_since_epoch))