Advertisement
Guest User

Untitled

a guest
Oct 26th, 2020
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 5.47 KB | None | 0 0
  1. using CsvHelper;
  2. using CsvHelper.Configuration;
  3. using CsvHelper.Configuration.Attributes;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Globalization;
  7. using System.IO;
  8. using System.Linq;
  9. using System.Text;
  10. using System.Text.RegularExpressions;
  11. using System.Threading.Tasks;
  12.  
  13. namespace ConsoleApp1
  14. {
  15.     public class Program
  16.     {
  17.         private static readonly string BASE_DIR = Environment.ExpandEnvironmentVariables(@"%USERPROFILE%\Downloads\deaths\");
  18.         private static readonly string[] SOURCE_FILES = new string[]
  19.         {
  20.             $@"{BASE_DIR}\deces-2018.csv",
  21.             $@"{BASE_DIR}\deces-2019.csv",
  22.             $@"{BASE_DIR}\deces-2020-m01.csv",
  23.             $@"{BASE_DIR}\Deces_2020_M02.csv",
  24.             $@"{BASE_DIR}\Deces_2020_M03.csv",
  25.             $@"{BASE_DIR}\Deces_2020_M04.csv",
  26.             $@"{BASE_DIR}\Deces_2020_M05.csv",
  27.             $@"{BASE_DIR}\Deces_2020_M06.csv",
  28.             $@"{BASE_DIR}\Deces_2020_M07.csv",
  29.             $@"{BASE_DIR}\Deces_2020_M08.csv",
  30.             $@"{BASE_DIR}\Deces_2020_M09.csv",
  31.         };
  32.         private static readonly string DESTINATION_FILE = $@"{BASE_DIR}\deces_out.csv";
  33.  
  34.         public static async Task Main(string[] args)
  35.         {
  36.             Console.WriteLine("Starting");
  37.             try
  38.             {
  39.                 var program = new Program();
  40.                 await program.Run();
  41.             }
  42.             catch (Exception ex)
  43.             {
  44.                 Console.WriteLine("ERROR");
  45.                 Console.WriteLine(ex.ToString());
  46.             }
  47.             Console.WriteLine("Stopping (press enter to exit)");
  48.             Console.ReadLine();
  49.         }
  50.  
  51.         public Task Run()
  52.         {
  53.             // Initialize empty date/deaths mapping
  54.             var deaths = new Dictionary<DateTime, int>();
  55.             var startPeriod = new DateTime(2018, 01, 01);
  56.             var endPeriod = new DateTime(2020, 09, 21);
  57.             for (DateTime date = startPeriod; date <= endPeriod; date = date.AddDays(1))
  58.             {
  59.                 deaths[date] = 0;
  60.             }
  61.  
  62.             // Compute daily deaths from input CSV files
  63.             Console.WriteLine("Reading input files...");
  64.             foreach (string sourceFile in SOURCE_FILES)
  65.             {
  66.                 // Read CSV file
  67.                 using var reader = new StreamReader(sourceFile, detectEncodingFromByteOrderMarks: true);
  68.                 using var csvReader = new CsvReader(reader, configuration: new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = ";", HasHeaderRecord = true });
  69.                 IEnumerable<InputEntry> inputEntries = csvReader.GetRecords<InputEntry>();
  70.  
  71.                 // Process all CSV entries
  72.                 int index = 0;
  73.                 foreach (InputEntry inputEntry in inputEntries)
  74.                 {
  75.                     index++;
  76.  
  77.                     // Parse death date
  78.                     Match match = Regex.Match(inputEntry.DeathDate, @"(\d\d\d\d)(\d\d)(\d\d)");
  79.  
  80.                     // Ignore & log entries with an invalid date format
  81.                     if (!match.Success)
  82.                     {
  83.                         Console.WriteLine($"Found invalid date format '{inputEntry.DeathDate}' in file '{sourceFile}' at index {index}.");
  84.                         continue;
  85.                     }
  86.  
  87.                     int year = int.Parse(match.Groups[1].Value);
  88.                     int month = int.Parse(match.Groups[2].Value);
  89.                     int day = int.Parse(match.Groups[3].Value);
  90.  
  91.                     // 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.
  92.                     // Move them to the 1st day of the month / 1st month of the year, the amount is negligible anyway.
  93.                     month = Math.Max(month, 1);
  94.                     day = Math.Max(day, 1);
  95.  
  96.                     // Ignore & log invalid dates
  97.                     if (!DateTime.TryParse($"{year:0000}-{month:00}-{day:00}", out DateTime deathDate))
  98.                     {
  99.                         Console.WriteLine($"Found invalid date '{inputEntry.DeathDate}' in file '{sourceFile}' at index {index}.");
  100.                         continue;
  101.                     }
  102.  
  103.                     // Ignore deaths outside of the observed period
  104.                     if (deaths.ContainsKey(deathDate))
  105.                     {
  106.                         deaths[deathDate]++;
  107.                     }
  108.                 }
  109.             }
  110.  
  111.             // Write daily deaths to output CSV file
  112.             Console.WriteLine("Writing ouput file...");
  113.             var outputEntries = deaths
  114.                 .OrderBy(x => x.Key)
  115.                 .Select(x => new OutputEntry() { Date = x.Key.ToString("yyyy-MM-dd"), Deaths = x.Value })
  116.                 .ToList();
  117.             using var writer = new StreamWriter(DESTINATION_FILE, append: false, encoding: Encoding.UTF8);
  118.             using var csvWriter = new CsvWriter(writer, configuration: new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = ";", HasHeaderRecord = true });
  119.             csvWriter.WriteRecords(outputEntries);
  120.  
  121.             return Task.CompletedTask;
  122.         }
  123.     }
  124.  
  125.     public class InputEntry
  126.     {
  127.         [Name("datedeces")]
  128.         public string DeathDate { get; set; }
  129.     }
  130.  
  131.     public class OutputEntry
  132.     {
  133.         [Name("date")]
  134.         public string Date { get; set; }
  135.         [Name("deaths")]
  136.         public int Deaths { get; set; }
  137.     }
  138. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement