Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using CsvHelper;
- using CsvHelper.Configuration;
- using CsvHelper.Configuration.Attributes;
- using System;
- using System.Collections.Generic;
- using System.Globalization;
- using System.IO;
- using System.Linq;
- using System.Text;
- using System.Text.RegularExpressions;
- using System.Threading.Tasks;
- namespace ConsoleApp1
- {
- public class Program
- {
- private static readonly string BASE_DIR = Environment.ExpandEnvironmentVariables(@"%USERPROFILE%\Downloads\deaths\");
- private static readonly string[] SOURCE_FILES = new string[]
- {
- $@"{BASE_DIR}\deces-2018.csv",
- $@"{BASE_DIR}\deces-2019.csv",
- $@"{BASE_DIR}\deces-2020-m01.csv",
- $@"{BASE_DIR}\Deces_2020_M02.csv",
- $@"{BASE_DIR}\Deces_2020_M03.csv",
- $@"{BASE_DIR}\Deces_2020_M04.csv",
- $@"{BASE_DIR}\Deces_2020_M05.csv",
- $@"{BASE_DIR}\Deces_2020_M06.csv",
- $@"{BASE_DIR}\Deces_2020_M07.csv",
- $@"{BASE_DIR}\Deces_2020_M08.csv",
- $@"{BASE_DIR}\Deces_2020_M09.csv",
- };
- private static readonly string DESTINATION_FILE = $@"{BASE_DIR}\deces_out.csv";
- public static async Task Main(string[] args)
- {
- Console.WriteLine("Starting");
- try
- {
- var program = new Program();
- await program.Run();
- }
- catch (Exception ex)
- {
- Console.WriteLine("ERROR");
- Console.WriteLine(ex.ToString());
- }
- Console.WriteLine("Stopping (press enter to exit)");
- Console.ReadLine();
- }
- public Task Run()
- {
- // Initialize empty date/deaths mapping
- var deaths = new Dictionary<DateTime, int>();
- var startPeriod = new DateTime(2018, 01, 01);
- var endPeriod = new DateTime(2020, 09, 21);
- for (DateTime date = startPeriod; date <= endPeriod; date = date.AddDays(1))
- {
- deaths[date] = 0;
- }
- // Compute daily deaths from input CSV files
- Console.WriteLine("Reading input files...");
- foreach (string sourceFile in SOURCE_FILES)
- {
- // Read CSV file
- using var reader = new StreamReader(sourceFile, detectEncodingFromByteOrderMarks: true);
- using var csvReader = new CsvReader(reader, configuration: new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = ";", HasHeaderRecord = true });
- IEnumerable<InputEntry> inputEntries = csvReader.GetRecords<InputEntry>();
- // Process all CSV entries
- int index = 0;
- foreach (InputEntry inputEntry in inputEntries)
- {
- index++;
- // Parse death date
- Match match = Regex.Match(inputEntry.DeathDate, @"(\d\d\d\d)(\d\d)(\d\d)");
- // Ignore & log entries with an invalid date format
- if (!match.Success)
- {
- Console.WriteLine($"Found invalid date format '{inputEntry.DeathDate}' in file '{sourceFile}' at index {index}.");
- continue;
- }
- int year = int.Parse(match.Groups[1].Value);
- int month = int.Parse(match.Groups[2].Value);
- int day = int.Parse(match.Groups[3].Value);
- // Some deaths are dated on the day "0" of the month or on the month "0" of the year, probably because the exact date is uncertain.
- // Move them to the 1st day of the month / 1st month of the year, the amount is negligible anyway.
- month = Math.Max(month, 1);
- day = Math.Max(day, 1);
- // Ignore & log invalid dates
- if (!DateTime.TryParse($"{year:0000}-{month:00}-{day:00}", out DateTime deathDate))
- {
- Console.WriteLine($"Found invalid date '{inputEntry.DeathDate}' in file '{sourceFile}' at index {index}.");
- continue;
- }
- // Ignore deaths outside of the observed period
- if (deaths.ContainsKey(deathDate))
- {
- deaths[deathDate]++;
- }
- }
- }
- // Write daily deaths to output CSV file
- Console.WriteLine("Writing ouput file...");
- var outputEntries = deaths
- .OrderBy(x => x.Key)
- .Select(x => new OutputEntry() { Date = x.Key.ToString("yyyy-MM-dd"), Deaths = x.Value })
- .ToList();
- using var writer = new StreamWriter(DESTINATION_FILE, append: false, encoding: Encoding.UTF8);
- using var csvWriter = new CsvWriter(writer, configuration: new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = ";", HasHeaderRecord = true });
- csvWriter.WriteRecords(outputEntries);
- return Task.CompletedTask;
- }
- }
- public class InputEntry
- {
- [Name("datedeces")]
- public string DeathDate { get; set; }
- }
- public class OutputEntry
- {
- [Name("date")]
- public string Date { get; set; }
- [Name("deaths")]
- public int Deaths { get; set; }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement