Determining when to download a file based on DateTime

There is a file that needs to be downloaded, the file is ready to download every day at 8pm, as it gets updated by a third party. The file is only downloaded when the user hits a certain page. This file is an external resource required to display the latest information. When the file is downloaded the time is stored with the file. So we know,

  1. when the file needs to be downloaded,
  2. what time the last file was downloaded,
  3. we know what the current time is. How would I make sure when to download the file or not based on what we know above.

Here is the test I tried, but this doesn't work:

DateTime currentFileDownloadedTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 10, 00, 0);
DateTime currentTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 10, 01, 15);
DateTime downloadTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 20, 0, 0);

if (currentFileDownloadedTime.Date.Day <= currentTime.Day &&
            (currentTime.TimeOfDay.TotalMilliseconds > currentFileDownloadedTime.TimeOfDay.TotalMilliseconds) &&
            (currentTime.TimeOfDay.TotalMilliseconds > downloadTime.TimeOfDay.TotalMilliseconds))
        {
            Console.WriteLine("Downloading File");
        }
Jon Skeet
people
quotationmark

I would take an approach of:

  • Determine the most recent publication time
  • Check whether the current file was downloaded after that

I'd do this with my Noda Time, using Instant as the result of the first step and the value I'd remember in terms of the "last download time" but you can do it with DateTime too... I'd suggest keeping everything in UTC, and using TimeZoneInfo to convert. (I'd make the time zone configurable, and don't assume anything about the system time zone. That keeps things flexible...)

To work out the most recent publication time, I'd:

  • Take the current time (in UTC)
  • Work out what the local date and time is in the target time zone
    • If the time is later than 8pm, then work out the UTC time corresponding to 8pm on the computed date, in the given time zone.
    • Otherwise, work out the UTC time corresponding to 8pm on the day before the computed date

So something like (untested):

// TODO: Extract an IClock interface that has a SystemClock
// implementation and a FakeClock implementation - then you
// can write lots of unit tests for this.
DateTime utcNow = DateTime.UtcNow;
TimeZoneInfo zone = ...; // South Africa (parameter?)
TimeSpan publishTimeOfDay = ...; // 8pm (parameter?)

DateTime localNow = TimeZoneInfo.ConvertTime(utcNow, zone);
DateTime publishDate = localNow.TimeOfDay >= postTimeOfDay
    ? localNow.Date : localNow.Date.AddDays(-1);
DateTime localPublishDateTime = publishDate + publishTimeOfDay;
return TimeZoneInfo.ConvertTimeToUtc(localPublishDateTime, zone);

people

See more on this question at Stackoverflow