def get_national_holidays(begin, end): """return french national days off between begin and end""" begin = Date(begin.year, begin.month, begin.day) end = Date(end.year, end.month, end.day) holidays = [strptime(datestr, '%Y-%m-%d') for datestr in list(FRENCH_MOBILE_HOLIDAYS.values())] for year in range(begin.year, end.year+1): for datestr in list(FRENCH_FIXED_HOLIDAYS.values()): date = strptime(datestr % year, '%Y-%m-%d') if date not in holidays: holidays.append(date) return [day for day in holidays if begin <= day < end]
def datefactory(year, month, day, sampledate): # assume date is either a python datetime or a mx.DateTime object if isinstance(sampledate, datetime): return datetime(year, month, day) if isinstance(sampledate, date): return date(year, month, day) return Date(year, month, day)
def __init__(self, locked=False): init_dict = self.__init_dict__ for key in init_dict: value = init_dict[key] date, mo, da, ye, time, ho, mi, se = [None] * 8 if type(value) in [str, unicode]: date, mo, da, ye, time, ho, mi, se = reDateTime.match( value).groups() if type(init_dict[key]) == dict: setattr(self, key, makeFMData( init_dict[key], locked=False)) # lock all substructures?? elif type(init_dict[key]) == list: l = [] for d in init_dict[key]: if type(d) == dict: l.append(makeFMData(d)) # lock ?? else: l.append(d) setattr(self, key, l) elif date and time: setattr( self, key, DateTime(int(ye), int(mo), int(da), int(ho), int(mi), int(se))) elif date: setattr(self, key, Date(int(ye), int(mo), int(da))) elif time: setattr(self, key, Time(int(ho), int(mi), int(se))) else: setattr(self, key, init_dict[key]) if locked: self.__modified__.add('__locked__')
def datefactory(year: int, month: int, day: int, sampledate: Union[date, datetime]) -> Union[date, datetime]: # assume date is either a python datetime or a mx.DateTime object if isinstance(sampledate, datetime): return datetime(year, month, day) if isinstance(sampledate, date): return date(year, month, day) return Date(year, month, day)
def has_leave(self, date=Date(*time.localtime()[:3])): """If the employment is on leave, e.g. working somewhere else temporarily. """ for l in self.leave: if l['start_date'] <= date and (date <= l['end_date']): return True return False
def test_within_bounds(self): self.assertEqual(self.c1.after_start(Date(2003,1,1)), False) self.assertEqual(self.c1.after_start(Date(2004,1,5)), False) self.assertEqual(self.c1.after_start(Date(2004,1,6)), True) self.assertEqual(self.c1.after_start(Date(2005,1,1)), True) self.assertEqual(self.c1.before_stop(Date(2003,1,1)), True) self.assertEqual(self.c1.before_stop(Date(2006,12,30)), False)
def is_active(self, date=Date(*time.localtime()[:3])): # IVR 2009-04-29 Lars Gustav Gudbrandsen requested on 2009-04-22 that # all employment-related info should be considered active 14 days # prior to the actual start day. # Jazz 2011-03-23: In order to avoid revoking affiliations/priviledges # for people changing role/position at UiO we should let the # affiliation be valid for a few days after it has been revoked # in the authoritative source if self.start: return ((self.start - DateTimeDelta(14) <= date) and ((not self.end) or (date <= self.end + DateTimeDelta(3)))) return ((not self.end) or (date <= self.end + DateTimeDelta(3)))
def has_active_employments(self, timepoint=Date(*time.localtime()[:3])): """Decide whether this person has employments at a given timepoint.""" for x in self.iteremployment(): if ((x.kind in (x.HOVEDSTILLING, x.BISTILLING) and x.is_active(timepoint)) or # IVR 2007-01-19 FIXME: # This is a horrible, gruesome, vile, # ugly, repulsive and hairy pile of crud. # It MUST DIE, once we get rid of LT. (x.kind == x.GJEST and x.code == "POLS-ANSAT")): return True return False
def _make_mxdate(self, text, format="%Y%m%d"): """Helper method to convert strings to dates. @param text: A string containing formatted date. The string may be empty. @type text: basestring @param format: A format string (cf. strptime) describing the datum in text. @type format: basestring @return @rtype: mx.DateTime.Date """ if not text: return None year, month, day = time.strptime(text, format)[:3] return Date(year, month, day)
def test_type_roundtrip_date_array(self): self._test_type_roundtrip_array(Date(2010, 5, 3))
def test_type_roundtrip_date(self): self._test_type_roundtrip(Date(2010, 5, 3))
def DateFromTicks(ticks): """Convert UNIX ticks into a mx.DateTime.Date.""" return Date(*localtime(ticks)[:3])
def test_date(self): data = [Date(2004,1,1), Date(1900,12,31), Date(2050,2,28), None] self._test_array(soomarray.ArrayDate, data)
def next_object(self, element): def get_value(element_value): return ensure_unicode(element_value, self.encoding) def extract(element_attr): return get_value(element.get(element_attr, "")) result = HRDataPerson() # Pull out all names self._register_names(result, element) # Pull out fnr tmp = "%02d%02d%02d%05d" % tuple([ int(element.get(x)) for x in ("fodtdag", "fodtmnd", "fodtar", "personnr") ]) fnr = fodselsnr.personnr_ok(tmp) result.add_id(result.NO_SSN, fnr) # Since LT does not provide birth date directly, we extract it from fnr result.birth_date = Date(*fodselsnr.fodt_dato(fnr)) # ... and gender if fodselsnr.er_mann(fnr): result.gender = result.GENDER_MALE else: result.gender = result.GENDER_FEMALE # fi # Register address # extract = lambda y: ensure_unicode(element.get(y, ""), self.encoding) result.address = DataAddress( kind=DataAddress.ADDRESS_PRIVATE, street=(extract("adresselinje1_privatadresse"), extract("adresselinje2_privatadresse")), zip=extract("poststednr_privatadresse"), city=extract("poststednavn_privatadresse")) # Contact information and jobs # FIXME: We do not have anything more intelligent for priorities priorities = dict() for sub in element.getiterator(): if sub.tag in ( "bilag", "gjest", "tils", ): emp = self._make_employment(sub) result.add_employment(emp) elif sub.tag in ( "komm", "arbtlf", ): for contact in self._make_contact(sub, priorities): result.add_contact(contact) # od # od # Reservation rules. Roughly, all employees are not reserved, unless # they say otherwise. Everyone else *is* reserved, unless they # explicitly allow publication in catalogues. has_active = result.has_active_employments() if has_active: to_reserve = False for resv in element.findall("res"): if (resv.get("katalogkode") == "ELKAT" and resv.get("felttypekode") not in ("PRIVADR", "PRIVTLF") and resv.get("resnivakode") != "SAMTYKKE"): to_reserve = True else: to_reserve = True for resv in element.findall("res"): if (resv.get("katalogkode") == "ELKAT" and resv.get("felttypekode") not in ("PRIVADR", "PRIVTLF")): to_reserve = resv.get("resnivakode") != "SAMTYKKE" result.reserved = to_reserve if (element.get("fakultetnr_for_lonnsslip") and element.get("instituttnr_for_lonnsslip") and element.get("gruppenr_for_lonnsslip")): result.primary_ou = (cereconf.DEFAULT_INSTITUSJONSNR, extract("fakultetnr_for_lonnsslip"), extract("instituttnr_for_lonnsslip"), extract("gruppenr_for_lonnsslip")) if not (result.get_name(result.NAME_FIRST) and result.get_name(result.NAME_LAST)): raise AssertionError("Missing name for %s" % list(result.iterids())) return result
def test_type_roundtrip_date_array(self): from mx.DateTime import Date self._test_type_roundtrip_array(Date(2010, 5, 3))
def _make_mxdate(self, text, format="%Y-%m-%d"): try: year, month, day = time.strptime(text, format)[:3] except ValueError: return None return Date(year, month, day)
def build_employee_cache(db, sysname, filename): """Build a mapping of primary account names for employees to their employment status. Employment status in this case is a pair of booleans, that tell whether the person with that primary account has tilsettinger and bilag that we need. :Parameters: db : a Database instance DB connection to Cerebrum. sysname : basestring Name of the authoritative system whence the data comes filename : basestring XML file name (source file) """ logger.debug("Building employee cache") # Cache *all* primary accounts. This helps us bind a primary account to an # fnr in the XML data. db_person = Factory.get("Person")(db) const = Factory.get("Constants")(db) logger.debug("Fetching all fnr->account mappings...") fnr2uname = db_person.getdict_external_id2primary_account( const.externalid_fodselsnr) logger.debug("... done (%d mappings)", len(fnr2uname)) logger.debug("Fetching all passport-nr->account mappings...") pnr2uname = db_person.getdict_external_id2primary_account( const.externalid_pass_number) logger.debug("... done (%d mappings)", len(pnr2uname)) # Build mapping for the employees parser = system2parser(sysname)(filename, logger, False) # mapping from uname to employment status employee_cache = dict() for xmlperson in parser.iter_person(): fnr = xmlperson.get_id(xmlperson.NO_SSN) passport_nr = xmlperson.get_id(xmlperson.PASSNR) if not fnr and not passport_nr: logger.debug("Person %s has no fnr or passport-nr in XML source", list(xmlperson.iterids())) continue # Everyone with bilag more recent than 180 days old is eligible bilag = filter(lambda x: ((not x.end) or (x.end >= (Date(*time.localtime()[:3]) - DateTimeDeltaFromDays(180)))) and x.kind == x.BILAG, xmlperson.iteremployment()) # Add to cache, if found in Cerebrum either by fnr or passport-nr. # each entry is a pair, telling whether the person has active # tilsetting and bilag (in that order). We do not need to know *what* # they are, only that they exist. if fnr in fnr2uname: employee_cache[fnr2uname[fnr]] = (xmlperson. has_active_employments(), bool(bilag)) elif passport_nr in pnr2uname: employee_cache[pnr2uname[passport_nr]] = (xmlperson. has_active_employments(), bool(bilag)) else: logger.debug("Cerebrum failed to find primary account for person " "with fnr: %s, passport-nr: %s.", fnr, passport_nr) # IVR 2007-07-13 FIXME: Is this actually useful? del fnr2uname del pnr2uname logger.debug("employee_cache has %d uname->employment status mappings", len(employee_cache)) return employee_cache