def prepare_publication_date(record_dict): """ Adds search and API compatible _publication_date_search field. This date is the lowest year-month-day date from the interval or (partial) date. WHY: - The regular publication_date is not in a format ES can use for powerful date queries. - Nor is it in a format serializers can use directly (more of a convenience in their case). - It supports our effort to align DB record and ES record. NOTE: Keeping this function outside the class to make it easier to move when dealing with deposit. By then, if only called here, it can be merged in MetadataSchemaV1. :param record_dict: loaded Record dict """ parser = level0Expression("level0") date_or_interval = parser.parseString(record_dict['publication_date'])[0] # lower_strict() is available for EDTF Interval AND Date objects date_tuple = date_or_interval.lower_strict() record_dict['_publication_date_search'] = time.strftime( "%Y-%m-%d", date_tuple)
def fake_edtf_level_0(): """Generates a fake publication_date string.""" def fake_date(end_date=None): fake = Faker() date_pattern = ['%Y', '%m', '%d'] # make it less and less likely to get less and less parts of the date if random.choice([True, False]): date_pattern.pop() if random.choice([True, False]): date_pattern.pop() return fake.date("-".join(date_pattern), end_datetime=end_date) f_date = fake_date() # if interval if random.choice([True, False]): # get f_date as date object parser = level0Expression("level0") parsed_date = parser.parseString(f_date)[0] date_tuple = parsed_date.lower_strict()[:3] f_date_object = datetime.date(*date_tuple) interval_start = fake_date(end_date=f_date_object) return "/".join([interval_start, f_date]) return f_date
def _deserialize(self, value, attr, data, **kwargs): """Deserialize an EDTF Level 0 formatted date string. load()-equivalent operation. NOTE: Level 0 allows for an interval. NOTE: ``level0Expression`` tries hard to parse dates. For example, ``"2020-01-02garbage"`` will parse to the 2020-01-02 date. """ parser = level0Expression("level0") try: result = parser.parseString(value) if not result: raise ParseException() # check it is chronological if interval # NOTE: EDTF Date and Interval both have same interface # and date.lower_strict() <= date.upper_strict() is always # True for a Date result = result[0] if result.upper_strict() < result.lower_strict(): raise self.make_error("invalid") return ( super(EDTFDateString, self) ._deserialize(str(result), attr, data, **kwargs) ) except ParseException: raise self.make_error("invalid")