public void TestQuarterYear()
		{
			var qy = new QuarterYear(new DateTime(2014, 1, 1));
			Assert.AreEqual(2014, qy.Year);
			Assert.AreEqual(1, qy.Quarter);
			Assert.IsTrue(qy.IsValid);

			qy = new QuarterYear();
			Assert.IsFalse(qy.IsValid);
		}
        /// <summary>
        /// Enumerates through location code boundary features.
        /// </summary>
        /// <param name="quarterYear">A quarter year.</param>
        /// <param name="targetProjection">Optional. Provide to reproject from 2927.</param>
        /// <returns>Returns an <see cref="IEnumerable&lt;T&gt;"/> of <see cref="Feature"/> objects.</returns>
        public static IEnumerable<IFeature> EnumerateLocationCodeBoundaries(QuarterYear quarterYear, ProjectionInfo targetProjection = null)
        {
            var uri = new Uri(string.Format(_locCodeBoundariesShpUrlPattern, quarterYear.GetDateRange()[0], quarterYear.Quarter));
            // Get the path to the TEMP directory.
            string tempDirPath = Path.GetTempPath();
            string dir = Path.Combine(tempDirPath, Path.GetRandomFileName());
            DirectoryInfo dirInfo = Directory.CreateDirectory(dir);
            string shp_name = null;

            try
            {
                var client = new HttpClient();
                client.GetStreamAsync(uri).ContinueWith(st =>
                {
                    // Write the shapefile to a temporary location.
                    using (var zipArchive = new ZipArchive(st.Result, ZipArchiveMode.Read))
                    {
                        foreach (var entry in zipArchive.Entries)
                        {
                            using (var outfile = File.Create(Path.Combine(dir, entry.Name)))
                            using (var sourcefile = entry.Open())
                            {
                                sourcefile.CopyToAsync(outfile).Wait();
                            }
                            if (entry.Name.EndsWith(".shp", StringComparison.InvariantCultureIgnoreCase))
                            {
                                shp_name = Path.Combine(dir, entry.Name);
                            }
                        }
                    }
                }).Wait();

                foreach (var kvp in EnumerateLocationCodeBoundaries(shp_name, targetProjection))
                {
                    yield return kvp;
                }

            }
            finally
            {
                dirInfo.Delete(true);
            }
        }
 public static IEnumerable<IFeature> EnumerateLocationCodeBoundariesWithTaxRates(QuarterYear quarterYear, ProjectionInfo targetProjection = null)
 {
     ILookup<string, TaxRateItem> taxRates = EnemerateTaxRates(quarterYear).ToLookup(item => item.LocationCode);
     IEnumerable<IFeature> boundaries = EnumerateLocationCodeBoundaries(quarterYear, targetProjection);
     foreach (var b in boundaries)
     {
         var taxRateInfo = taxRates[(string)b.DataRow[1]].First();
         // Add data columns.
         b.DataRow.Table.Columns.AddRange(new DataColumn[] {
             new DataColumn("Name", typeof(string)),
             new DataColumn("State", typeof(float)),
             new DataColumn("Local", typeof(float)),
             new DataColumn("Rta", typeof(float)),
             new DataColumn("Rate", typeof(float)),
             new DataColumn("EffectiveDate", typeof(DateTime)),
             new DataColumn("ExpirationDate", typeof(DateTime))
         });
         // Rename the LOCCODE column.
         b.DataRow.Table.Columns["LOCCODE"].ColumnName = "LocationCode";
         b.DataRow.SetField("Name", taxRateInfo.Name);
         b.DataRow.SetField("State", taxRateInfo.State);
         b.DataRow.SetField("Local", taxRateInfo.Local);
         b.DataRow.SetField("Rta", taxRateInfo.Rta);
         b.DataRow.SetField("Rate", taxRateInfo.Rate);
         b.DataRow.SetField("EffectiveDate", taxRateInfo.EffectiveDate);
         b.DataRow.SetField("ExpirationDate", taxRateInfo.ExpirationDate);
         yield return b;
     }
 }
        /// <summary>
        /// Gets the tax rates for the given date. If no date is given, <see cref="DateTime.Today"/> is assumed.
        /// </summary>
        /// <param name="quarterYear">A quarter year.</param>
        /// <returns>Enumeration of <see cref="TaxRateItem"/></returns>
        public static IEnumerable<TaxRateItem> EnemerateTaxRates(QuarterYear quarterYear)
        {
            Uri uri = new Uri(string.Format(_urlPattern, quarterYear.Year, quarterYear.Quarter));

            var client = new HttpClient();
            Stream zipStream = null;

            client.GetStreamAsync(uri).ContinueWith(responseTask =>
            {
                zipStream = responseTask.Result;
            }).Wait();

            return EnumerateZippedTaxRateCsv(zipStream);
        }