Skip to main content
4 of 4
added 11 characters in body
Ben W
  • 23.1k
  • 3
  • 19
  • 43

I would use PyQGIS along with Python's datetime and csv modules for this. Copy and paste the script below into a new editor in the Python console. You will just need to edit the output path for the CSV file and the name of the text field in your GeoPackage (see comments in the code), then select your gpkg as the active layer and run the script.

from datetime import datetime, timedelta

import csv

# Edit the line below to the path where you want your output csv written
output_csv = 'Path/To/Attributes.csv'

# Edit below to match the name of the text field in your GeoPackage
fld_name = 'Your Field Name'

lyr = iface.activeLayer()

csv_tbl = open(output_csv, mode='w', newline='')
writer = csv.writer(csv_tbl)
writer.writerow(['Column1', 'Column2'])

for ft in lyr.getFeatures():
    attr = ft[fld_name]
    start_date_txt = attr.split('to')[0][-11:][:-1]
    start_date = datetime.strptime(start_date_txt, '%Y_%m_%d').date()
    writer.writerow([attr, start_date_txt])
    end_date_txt = attr.split('to')[1][1:]
    end_date = datetime.strptime(end_date_txt, '%Y_%m_%d').date()
    gaps = end_date - start_date
    gap_days = gaps.days-1
    day_count = 1
    for i in range(gap_days):
        fill_date = start_date+timedelta(days=day_count)
        fill_date_txt = datetime.strftime(fill_date, '%Y_%m_%d')
        writer.writerow([attr, fill_date_txt])
        day_count+=1
    writer.writerow([attr, end_date_txt])
    
csv_tbl.close()
del writer

print('Done')

I tested with this dummy geopackage (one string field containing the information).

enter image description here

After running the above script (shown here in the Python console)

enter image description here

The output CSV file was produced:

enter image description here

Edit:

To adapt the script to write the location to a third column, we just need to extract it from the attribute string. In this case we can simply split the string with the underscore character and access the first element (index 0) of the list returned by the split() method. We then add it to the list of values passed to each writerow() call on the csv writer object.

I have also added comments to the adapted code to help you step through the logic. For what it's worth, the string manipulation could probably be done more 'slickly' with Regexp but I'm far from competent with Regexp so here we are!

from datetime import datetime, timedelta

import csv

# Edit the line below to the path where you want your output csv written
output_csv = 'Path/To/Attributes.csv'

# Edit below to match the name of the text field in your GeoPackage
fld_name = 'Your Field Name'

# Get the active layer
lyr = iface.activeLayer()

# Open the CSV table for writing
csv_tbl = open(output_csv, mode='w', newline='')

# Create a csv writer object
writer = csv.writer(csv_tbl)

# Write the column headers
writer.writerow(['Column1', 'Column2', 'Column3'])

# Iterate over the geopackage layer features
for ft in lyr.getFeatures():
    # Get the features value from the relevant field
    attr = ft[fld_name]
    # Split out the location part of the string
    location = attr.split('_')[0]
    # Split out the start date as a string using split() plus string slicing
    start_date_txt = attr.split('to')[0][-11:][:-1]
    # convert the start date text to an actual Python date object
    start_date = datetime.strptime(start_date_txt, '%Y_%m_%d').date()
    # Write row to csv
    writer.writerow([attr, start_date_txt, location])
    # Split out end date as a string
    end_date_txt = attr.split('to')[1][1:]
    # Convert to Python date object
    end_date = datetime.strptime(end_date_txt, '%Y_%m_%d').date()
    # Subtract start date from end date to calculate difference in days
    gaps = end_date - start_date
    # Subtract one day to get number of dates to fill in
    gap_days = gaps.days-1
    # Initialize day counter
    day_count = 1
    # Create the number of new date objects required adding 1 day on each iteration
    for i in range(gap_days):
        fill_date = start_date+timedelta(days=day_count)
        # Convert the date back to a string separated by underscores
        fill_date_txt = datetime.strftime(fill_date, '%Y_%m_%d')
        # Write row to csv
        writer.writerow([attr, fill_date_txt, location])
        # Increment the day counter
        day_count+=1
    # Write row to csv
    writer.writerow([attr, end_date_txt, location])

# Close the csv table and delete the writer object to release the csv file
csv_tbl.close()
del writer

print('Done')
Ben W
  • 23.1k
  • 3
  • 19
  • 43