# ------------------------ widgets.py
from django import forms
from django.utils.encoding import force_unicode
from django.utils.safestring import mark_safe
from settings import STATIC_URL
import datetime,time
from utils import date_convert
calbtn = u'''
'''
calbtn = calbtn.replace("{STATIC_URL}", STATIC_URL)
class DateTimeWidget(forms.widgets.TextInput):
class Media:
css = {
'all': (STATIC_URL + 'jscalendar/styles/skins/calendar-system.css',)
}
js = (
STATIC_URL + 'jscalendar/js/jalali.js',
STATIC_URL + 'jscalendar/js/calendar.js',
STATIC_URL + 'jscalendar/js/calendar-setup.js',
STATIC_URL + 'jscalendar/js/lang/calendar-fa.js',
)
dformat = '%Y-%m-%d'
def render(self, name, value, attrs=None):
if value is None: value = ''
final_attrs = self.build_attrs(attrs, type=self.input_type, name=name)
if value != '':
try:
final_attrs['value'] = \
force_unicode(value.strftime(self.dformat))
except:
final_attrs['value'] = \
force_unicode(value)
if not final_attrs.has_key('id'):
final_attrs['id'] = u'%s_id' % (name)
id = final_attrs['id']
jsdformat = self.dformat #.replace('%', '%%')
cal = calbtn % (id, id, id, id, jsdformat)
parsed_atts = forms.util.flatatt(final_attrs)
dat_f = date_convert.gregorian_to_jalali(value,'-')
a = u' %s%s' % (id,dat_f, parsed_atts, self.media, cal)
return mark_safe(a)
def value_from_datadict(self, data, files, name):
dtf = forms.fields.DEFAULT_DATETIME_INPUT_FORMATS
empty_values = forms.fields.EMPTY_VALUES
value = data.get(name, None)
if value in empty_values:
return None
if isinstance(value, datetime.datetime):
return value
if isinstance(value, datetime.date):
return datetime.datetime(value.year, value.month, value.day)
for format in dtf:
try:
# print "%s %s %s" %(value,format,time.strptime(value, format)[:6])
dst = time.strptime(value, format)[:6] # date string tuple
return datetime.datetime(dst[0],dst[1],dst[2])
except ValueError:
continue
# except Exception,e:
# return e.message
return None
def _has_changed(self, initial, data):
'''
Return True if data differs from initial.
Copy of parent's method, but modify value with strftime function before final comparsion
'''
if data is None:
data_value = u''
else:
data_value = data
if initial is None:
initial_value = u''
else:
initial_value = initial
try:
if force_unicode(initial_value.strftime(self.dformat)) != force_unicode(data_value.strftime(self.dformat)):
return True
except:
if force_unicode(initial_value) != force_unicode(data_value):
return True
return False
#------------------------------------------------------------------------
#--------------- date_convert.py
from datetime import datetime, date, time
from calverter import calverter
def jalali_to_gregorian(dat_str):
'''
Gets date in (char(8)) (or / delimited) (or char(10) / delimited)
returns Date
returns None on error
'''
cal = calverter()
try:
year = None
month = None
day = None
if len(dat_str) == 8:
year = dat_str[0:4]
month = dat_str[4:6]
day = dat_str[6:8]
elif len(dat_str) == 10:
year = dat_str[0:4]
month = dat_str[5:7]
day = dat_str[8:10]
else:
splited = dat_str.split('/')
year = splited[0]
month = splited[1]
day = splited[2]
if not year.isdigit(): return None
if not month.isdigit(): return None
if not day.isdigit(): return None
jd = cal.jalali_to_jd(int(year),int(month),int(day))
dat_tuple = cal.jd_to_gregorian(jd)
return date(dat_tuple[0],dat_tuple[1],dat_tuple[2])
except Exception,msg:
# print msg
return None
def gregorian_to_jalali(date,sep='/'):
'''
Gets georgian date
returns persian date in char(10) (/ separated)
'''
if date == '' or date == None: return ''
cal = calverter()
date_str = str(date)
year = date_str[0:4]
month = date_str[5:7]
day = date_str[8:10]
jd = cal.gregorian_to_jd(int(year),int(month),int(day))
dat_tuple = cal.jd_to_jalali(jd)
format = "%s"+sep+"%s"+sep+"%s"
return format %(str(dat_tuple[0]).rjust(4,'0'),str(dat_tuple[1]).rjust(2,'0'),str(dat_tuple[2]).rjust(2,'0'))
def jalali_today():
date = datetime.now().date()
return gregorgian_to_jalali(date)
# ----------------------------------------------------------------------
#!/usr/bin/env python
## calverter.py (2008/08/16)
##
## Copyright (C) 2008 Mehdi Bayazee (Bayazee@Gmail.com)
##
## Iranian (Jalali) calendar:
## http://en.wikipedia.org/wiki/Iranian_calendar
## Islamic (Hijri) calendar:
## http://en.wikipedia.org/wiki/Islamic_calendar
## Gregorian calendar:
## http://en.wikipedia.org/wiki/Gregorian_calendar
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2, or (at your option)
## any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
__author__ = "Mehdi Bayazee"
__copyright__ = "Copyright (C) 2008 Mehdi Bayazee"
__revision__ = "$Id$"
__version__ = "0.1.5"
import math
class calverter:
def __init__(self):
self.J0000 = 1721424.5 # Julian date of Gregorian epoch: 0000-01-01
self.J1970 = 2440587.5 # Julian date at Unix epoch: 1970-01-01
self.JMJD = 2400000.5 # Epoch of Modified Julian Date system
self.J1900 = 2415020.5 # Epoch (day 1) of Excel 1900 date system (PC)
self.J1904 = 2416480.5 # Epoch (day 0) of Excel 1904 date system (Mac)
self.NormLeap = ("Normal year", "Leap year")
self.GREGORIAN_EPOCH = 1721425.5
self.GREGORIAN_WEEKDAYS = ("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday")
self.ISLAMIC_EPOCH = 1948439.5;
self.ISLAMIC_WEEKDAYS = ("al-ahad", "al-'ithnayn", "ath-thalatha'", "al-arbia`aa'", "al-khamis", "al-jumu`a", "as-sabt")
self.JALALI_EPOCH = 1948320.5;
self.JALALI_WEEKDAYS = ("Yekshanbeh", "Doshanbeh", "Seshhanbeh", "Chaharshanbeh", "Panjshanbeh", "Jomeh", "Shanbeh")
def jwday(self, j):
"JWDAY: Calculate day of week from Julian day"
return int(math.floor((j + 1.5))) % 7
def weekday_before(self, weekday, jd):
"""
WEEKDAY_BEFORE: Return Julian date of given weekday (0 = Sunday)
in the seven days ending on jd.
"""
return jd - self.jwday(jd - weekday)
def search_weekday(self, weekday, jd, direction, offset):
"""
SEARCH_WEEKDAY: Determine the Julian date for:
weekday Day of week desired, 0 = Sunday
jd Julian date to begin search
direction 1 = next weekday, -1 = last weekday
offset Offset from jd to begin search
"""
return self.weekday_before(weekday, jd + (direction * offset))
# Utility weekday functions, just wrappers for search_weekday
def nearest_weekday(self, weekday, jd):
return self.search_weekday(weekday, jd, 1, 3)
def next_weekday(self, weekday, jd):
return self.search_weekday(weekday, jd, 1, 7)
def next_or_current_weekday(self, weekday, jd):
return self.search_weekday(weekday, jd, 1, 6)
def previous_weekday(self, weekday, jd):
return self.search_weekday(weekday, jd, -1, 1)
def previous_or_current_weekday(self, weekday, jd):
return self.search_weekday(weekday, jd, 1, 0)
def leap_gregorian(self, year):
"LEAP_GREGORIAN: Is a given year in the Gregorian calendar a leap year ?"
return ((year % 4) == 0) and (not(((year % 100) == 0) and ((year % 400) != 0)))
def gregorian_to_jd(self, year, month, day):
"GREGORIAN_TO_JD: Determine Julian day number from Gregorian calendar date"
# Python <= 2.5
if month <= 2 :
tm = 0
elif self.leap_gregorian(year):
tm = -1
else:
tm = -2
# Python 2.5
#tm = 0 if month <= 2 else (-1 if self.leap_gregorian(year) else -2)
return (self.GREGORIAN_EPOCH - 1) + (365 * (year - 1)) + math.floor((year - 1) / 4) + (-math.floor((year - 1) / 100)) + \
math.floor((year - 1) / 400) + math.floor((((367 * month) - 362) / 12) + tm + day)
def jd_to_gregorian(self, jd) :
"JD_TO_GREGORIAN: Calculate Gregorian calendar date from Julian day"
wjd = math.floor(jd - 0.5) + 0.5
depoch = wjd - self.GREGORIAN_EPOCH
quadricent = math.floor(depoch / 146097)
dqc = depoch % 146097
cent = math.floor(dqc / 36524)
dcent = dqc % 36524
quad = math.floor(dcent / 1461)
dquad = dcent % 1461
yindex = math.floor(dquad / 365)
year = int((quadricent * 400) + (cent * 100) + (quad * 4) + yindex)
if not((cent == 4) or (yindex == 4)) :
year += 1
yearday = wjd - self.gregorian_to_jd(year, 1, 1)
# Python <= 2.5
if wjd < self.gregorian_to_jd(year, 3, 1):
leapadj = 0
elif self.leap_gregorian(year):
leapadj = 1
else:
leapadj = 2
# Python 2.5
#leapadj = 0 if wjd < self.gregorian_to_jd(year, 3, 1) else (1 if self.leap_gregorian(year) else 2)
month = int(math.floor((((yearday + leapadj) * 12) + 373) / 367))
day = int(wjd - self.gregorian_to_jd(year, month, 1)) + 1
return year, month, day
def n_weeks(self, weekday, jd, nthweek):
j = 7 * nthweek
if nthweek > 0 :
j += self.previous_weekday(weekday, jd)
else :
j += next_weekday(weekday, jd)
return j
def iso_to_julian(self, year, week, day):
"ISO_TO_JULIAN: Return Julian day of given ISO year, week, and day"
return day + self.n_weeks(0, self.gregorian_to_jd(year - 1, 12, 28), week)
def jd_to_iso(self, jd):
"JD_TO_ISO: Return array of ISO (year, week, day) for Julian day"
year = self.jd_to_gregorian(jd - 3)[0]
if jd >= self.iso_to_julian(year + 1, 1, 1) :
year += 1
week = int(math.floor((jd - self.iso_to_julian(year, 1, 1)) / 7) + 1)
day = self.jwday(jd)
if day == 0 :
day = 7
return year, week, day
def iso_day_to_julian(self, year, day):
"ISO_DAY_TO_JULIAN: Return Julian day of given ISO year, and day of year"
return (day - 1) + self.gregorian_to_jd(year, 1, 1)
def jd_to_iso_day(self, jd):
"JD_TO_ISO_DAY: Return array of ISO (year, day_of_year) for Julian day"
year = self.jd_to_gregorian(jd)[0]
day = int(math.floor(jd - self.gregorian_to_jd(year, 1, 1))) + 1
return year, day
def pad(self, Str, howlong, padwith) :
"PAD: Pad a string to a given length with a given fill character. "
s = str(Str)
while s.length < howlong :
s = padwith + s
return s
def leap_islamic(self, year):
"LEAP_ISLAMIC: Is a given year a leap year in the Islamic calendar ?"
return (((year * 11) + 14) % 30) < 11
def islamic_to_jd(self, year, month, day):
"ISLAMIC_TO_JD: Determine Julian day from Islamic date"
return (day + math.ceil(29.5 * (month - 1)) + \
(year - 1) * 354 + \
math.floor((3 + (11 * year)) / 30) + \
self.ISLAMIC_EPOCH) - 1
def jd_to_islamic(self, jd):
"JD_TO_ISLAMIC: Calculate Islamic date from Julian day"
jd = math.floor(jd) + 0.5
year = int(math.floor(((30 * (jd - self.ISLAMIC_EPOCH)) + 10646) / 10631))
month = int(min(12, math.ceil((jd - (29 + self.islamic_to_jd(year, 1, 1))) / 29.5) + 1))
day = int(jd - self.islamic_to_jd(year, month, 1)) + 1;
return year, month, day
def leap_jalali(self, year):
"LEAP_jalali: Is a given year a leap year in the Jalali calendar ?"
# Python <= 2.5
if year > 0:
rm = 474
else:
rm = 473
# Python 2.5
#return ((((((year - 474 if year > 0 else 473 ) % 2820) + 474) + 38) * 682) % 2816) < 682
return ((((((year - rm) % 2820) + 474) + 38) * 682) % 2816) < 682
def jalali_to_jd(self, year, month, day):
"JALALI_TO_JD: Determine Julian day from Jalali date"
# Python <= 2.5
if year >=0 :
rm = 474
else:
rm = 473
epbase = year - (rm)
# Python 2.5
#epbase = year - 474 if year>=0 else 473
epyear = 474 + (epbase % 2820)
if month <= 7 :
mm = (month - 1) * 31
else:
mm = ((month - 1) * 30) + 6
return day + mm + \
math.floor(((epyear * 682) - 110) / 2816) + \
(epyear - 1) * 365 + \
math.floor(epbase / 2820) * 1029983 + \
(self.JALALI_EPOCH - 1)
def jd_to_jalali(self, jd):
"JD_TO_JALALI: Calculate Jalali date from Julian day"
jd = math.floor(jd) + 0.5
depoch = jd - self.jalali_to_jd(475, 1, 1)
cycle = math.floor(depoch / 1029983)
cyear = depoch % 1029983
if cyear == 1029982 :
ycycle = 2820
else :
aux1 = math.floor(cyear / 366)
aux2 = cyear % 366
ycycle = math.floor(((2134 * aux1) + (2816 * aux2) + 2815) / 1028522) + aux1 + 1
year = int(ycycle + (2820 * cycle) + 474)
if year <= 0 :
year -= 1
yday = (jd - self.jalali_to_jd(year, 1, 1)) + 1
if yday <= 186:
month = int(math.ceil(yday / 31))
else:
month = int(math.ceil((yday - 6) / 30))
day = int(jd - self.jalali_to_jd(year, month, 1)) + 1
return year, month, day
# ----------------------------------------------------------------
# ----------------------- settings.py
STATIC_URL = '/static/'