0

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");
        }
Mike Barnes
  • 4,217
  • 18
  • 40
  • 64

3 Answers3

2

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);
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
1

Basically, you have to check if the time the client accesses is after 8 am of the current day. If you have clients from different timezones you have to normalize (convert to UTC).

DateTime nowUtc = TimeZoneInfo.ConvertTimeToUtc(DateTime.Now);
DateTime fileRefreshUtc = DateTime.Now.Today + new Timespan(6,0,0);
if(nowUtc > fileRefreshUtc && lastDownloaded < fileRefreshUtc)
{
    //download file
    lastDownloaded = DateTime.Now;
}

For more information how to check if the current time is in a specific range check this.

EDIT: Just realized that I forgot to check if the file was already downloaded. I've edited the code. The idea is that you construct a date (fileRefreshUtc) of the todays file refresh. Then you can check whether the current date is after the refresh and if you keep track of the last download time, you can check if the client has already downloaded the new file version.

Community
  • 1
  • 1
rene
  • 1,618
  • 21
  • 26
1

Don't use shenanigans to compare date, like comparing the day, the milliseconds or whatever. just compare the DateTime objects, it will work like a charm! Also try to only work with UTC time, it will make your work easier.

I take for granted your input are currentFileDownloadedTime, the time when you downloaded the file and uploadTime, the time when the remote file should be uploaded today.

You have to make a new download if you haven't already uploadTime > currentFileDownloadedTime and if you are later now than the upload time: DateTime.UtcNow > uploadTime.

So that gives

if((uploadTime > currentFileDownloadedTime) && (DateTime.UtcNow > uploadTime))
{
    Console.WriteLine("Downloading File");
}

Which is both short and easy to read.

Falanwe
  • 4,636
  • 22
  • 37