Поделиться через


Как определить, можно ли напечатать задание в данное время суток

Очереди печати не всегда доступны в течение 24 часов в день. Они имеют свойства времени начала и окончания, которые можно задать, чтобы сделать их недоступными в определенное время суток. Эту функцию можно использовать, например, для резервирования принтера для эксклюзивного использования определенного отдела после 5 вечера. Этот отдел будет иметь другую очередь обслуживания принтера, чем другие отделы. Очередь для других отделов будет недоступна после 5 вечера, в то время как очередь для предпочитаемого отдела может быть доступна в любое время.

Кроме того, задания печати могут быть настроены на печать только в течение определенного времени.

Классы PrintQueue и PrintSystemJobInfo, предоставляемые в API Microsoft .NET Framework, предоставляют средства для удаленной проверки того, может ли данное задание печати печатать в заданной очереди в текущее время.

Пример

Ниже приведен пример, который позволяет выявить проблемы с печатным заданием.

Существует два основных шага для такой функции, как показано ниже.

  1. Прочитайте свойства StartTimeOfDay и UntilTimeOfDayPrintQueue, чтобы определить, попадает ли текущее время в их диапазон.

  2. Прочитайте свойства StartTimeOfDay и UntilTimeOfDayPrintSystemJobInfo, чтобы определить, попадает ли текущее время в их диапазон.

Но осложнения возникают из-за того, что эти свойства не являются DateTime объектами. Вместо этого они представляют собой объекты Int32, которые выражают время дня в количестве минут, прошедших с полуночи. Кроме того, это не полночь в текущем часовом поясе, но полночь UTC (координированное универсальное время).

Первый пример кода представляет статический метод ReportQueueAndJobAvailability, которому передается PrintSystemJobInfo и который вызывает вспомогательные методы, чтобы определить, может ли задание быть напечатано в настоящий момент и, если нет, когда оно может быть напечатано. Обратите внимание, что PrintQueue не передается методу. Это связано с тем, что PrintSystemJobInfo содержит ссылку на очередь в своем свойстве HostingPrintQueue.

Подчиненные методы включают перегруженный метод ReportAvailabilityAtThisTime, который может принимать PrintQueue или PrintSystemJobInfo в качестве параметра. Также существует TimeConverter.ConvertToLocalHumanReadableTime. Все эти методы рассматриваются ниже.

Метод ReportQueueAndJobAvailability начинается с проверки того, недоступны ли очередь или задание в настоящее время. Если один из них недоступен, он проверяет, является ли очередь недоступной. Если он недоступен, метод сообщает об этом факте и время, когда очередь станет доступной снова. Затем она проверяет задание и, если оно недоступно, сообщает о следующем времени, когда можно будет распечатать. Наконец, метод сообщает самое раннее время, когда задание может быть распечатано. Это более позднее из двух приведённых времён.

  • Время следующей очереди печати.

  • Время, когда следующее задание печати будет доступно.

При составлении отчетов о времени суток метод ToShortTimeString также вызывается, так как этот метод подавляет годы, месяцы и дни выходных данных. Невозможно ограничить доступность очереди печати или задания печати на определенные годы, месяцы или дни.

static void ReportQueueAndJobAvailability (PrintSystemJobInfo^ theJob) 
{
   if (!(ReportAvailabilityAtThisTime(theJob->HostingPrintQueue) && ReportAvailabilityAtThisTime(theJob)))
   {
      if (!ReportAvailabilityAtThisTime(theJob->HostingPrintQueue))
      {
         Console::WriteLine("\nThat queue is not available at this time of day." + "\nJobs in the queue will start printing again at {0}", TimeConverter::ConvertToLocalHumanReadableTime(theJob->HostingPrintQueue->StartTimeOfDay).ToShortTimeString());
         // TimeConverter class is defined in the complete sample
      }
      if (!ReportAvailabilityAtThisTime(theJob))
      {
         Console::WriteLine("\nThat job is set to print only between {0} and {1}", TimeConverter::ConvertToLocalHumanReadableTime(theJob->StartTimeOfDay).ToShortTimeString(), TimeConverter::ConvertToLocalHumanReadableTime(theJob->UntilTimeOfDay).ToShortTimeString());
      }
      Console::WriteLine("\nThe job will begin printing as soon as it reaches the top of the queue after:");
      if (theJob->StartTimeOfDay > theJob->HostingPrintQueue->StartTimeOfDay)
      {
         Console::WriteLine(TimeConverter::ConvertToLocalHumanReadableTime(theJob->StartTimeOfDay).ToShortTimeString());
      } else
      {
         Console::WriteLine(TimeConverter::ConvertToLocalHumanReadableTime(theJob->HostingPrintQueue->StartTimeOfDay).ToShortTimeString());
      }

   }
};
internal static void ReportQueueAndJobAvailability(PrintSystemJobInfo theJob)
{
    if (!(ReportAvailabilityAtThisTime(theJob.HostingPrintQueue) && ReportAvailabilityAtThisTime(theJob)))
    {
        if (!ReportAvailabilityAtThisTime(theJob.HostingPrintQueue))
        {
            Console.WriteLine("\nThat queue is not available at this time of day." +
                "\nJobs in the queue will start printing again at {0}",
                 TimeConverter.ConvertToLocalHumanReadableTime(theJob.HostingPrintQueue.StartTimeOfDay).ToShortTimeString());
            // TimeConverter class is defined in the complete sample
        }

        if (!ReportAvailabilityAtThisTime(theJob))
        {
            Console.WriteLine("\nThat job is set to print only between {0} and {1}",
                TimeConverter.ConvertToLocalHumanReadableTime(theJob.StartTimeOfDay).ToShortTimeString(),
                TimeConverter.ConvertToLocalHumanReadableTime(theJob.UntilTimeOfDay).ToShortTimeString());
        }
        Console.WriteLine("\nThe job will begin printing as soon as it reaches the top of the queue after:");
        if (theJob.StartTimeOfDay > theJob.HostingPrintQueue.StartTimeOfDay)
        {
            Console.WriteLine(TimeConverter.ConvertToLocalHumanReadableTime(theJob.StartTimeOfDay).ToShortTimeString());
        }
        else
        {
            Console.WriteLine(TimeConverter.ConvertToLocalHumanReadableTime(theJob.HostingPrintQueue.StartTimeOfDay).ToShortTimeString());
        }
    }//end if at least one is not available
}//end ReportQueueAndJobAvailability
Friend Shared Sub ReportQueueAndJobAvailability(ByVal theJob As PrintSystemJobInfo)
    If Not(ReportAvailabilityAtThisTime(theJob.HostingPrintQueue) AndAlso ReportAvailabilityAtThisTime(theJob)) Then
        If Not ReportAvailabilityAtThisTime(theJob.HostingPrintQueue) Then
            Console.WriteLine(vbLf & "That queue is not available at this time of day." & vbLf & "Jobs in the queue will start printing again at {0}", TimeConverter.ConvertToLocalHumanReadableTime(theJob.HostingPrintQueue.StartTimeOfDay).ToShortTimeString())
            ' TimeConverter class is defined in the complete sample
        End If

        If Not ReportAvailabilityAtThisTime(theJob) Then
            Console.WriteLine(vbLf & "That job is set to print only between {0} and {1}", TimeConverter.ConvertToLocalHumanReadableTime(theJob.StartTimeOfDay).ToShortTimeString(), TimeConverter.ConvertToLocalHumanReadableTime(theJob.UntilTimeOfDay).ToShortTimeString())
        End If
        Console.WriteLine(vbLf & "The job will begin printing as soon as it reaches the top of the queue after:")
        If theJob.StartTimeOfDay > theJob.HostingPrintQueue.StartTimeOfDay Then
            Console.WriteLine(TimeConverter.ConvertToLocalHumanReadableTime(theJob.StartTimeOfDay).ToShortTimeString())
        Else
            Console.WriteLine(TimeConverter.ConvertToLocalHumanReadableTime(theJob.HostingPrintQueue.StartTimeOfDay).ToShortTimeString())
        End If

    End If 'end if at least one is not available

End Sub

Две перегрузки метода ReportAvailabilityAtThisTime идентичны, за исключением типа, переданного им, поэтому представлена только версия PrintQueue ниже.

Замечание

Тот факт, что методы идентичны, за исключением типа, вызывает вопрос о том, почему пример не создает универсальный метод ReportAvailabilityAtThisTime<T>. Причина заключается в том, что такой метод должен быть ограничен классом, который имеет StartTimeOfDay и Свойства UntilTimeOfDay, которые вызывает метод, но универсальный метод может быть ограничен только одним классом, а единственный класс, общий для обоих PrintQueue и PrintSystemJobInfo в дереве наследования, является PrintSystemObject, который не имеет таких свойств.

Метод ReportAvailabilityAtThisTime (представленный в приведенном ниже примере кода) начинается с инициализации переменной Boolean sentinel в true. Он будет сброшен на false, если очередь недоступна.

Затем метод проверяет, совпадают ли начальное время и время "до". Если они есть, очередь всегда доступна, поэтому метод возвращает true.

Если очередь недоступна в любое время, метод использует свойство статического UtcNow для получения текущего времени в качестве объекта DateTime. (Не требуется локальное время, так как свойства StartTimeOfDay и UntilTimeOfDay сами находятся в формате UTC.)

Однако эти два свойства не являются DateTime объектами. Они Int32выражают время, как количество минут после полуночи в формате UTC. Поэтому нам нужно преобразовать объект DateTime в минуты после полуночи. После этого метод просто проверяет, находится ли значение "now" между началом очереди и временем "до", задает для sentinel значение false, если "сейчас" не между двумя разами, и возвращает sentinel.

static Boolean ReportAvailabilityAtThisTime (PrintQueue^ pq) 
{
   Boolean available = true;
   if (pq->StartTimeOfDay != pq->UntilTimeOfDay)
   {
      DateTime utcNow = DateTime::UtcNow;
      Int32 utcNowAsMinutesAfterMidnight = (utcNow.TimeOfDay.Hours * 60) + utcNow.TimeOfDay.Minutes;

      // If now is not within the range of available times . . .
      if (!((pq->StartTimeOfDay < utcNowAsMinutesAfterMidnight) && (utcNowAsMinutesAfterMidnight < pq->UntilTimeOfDay)))
      {
         available = false;
      }
   }
   return available;
};
private static Boolean ReportAvailabilityAtThisTime(PrintQueue pq)
{
    Boolean available = true;
    if (pq.StartTimeOfDay != pq.UntilTimeOfDay) // If the printer is not available 24 hours a day
    {
        DateTime utcNow = DateTime.UtcNow;
        Int32 utcNowAsMinutesAfterMidnight = (utcNow.TimeOfDay.Hours * 60) + utcNow.TimeOfDay.Minutes;

        // If now is not within the range of available times . . .
        if (!((pq.StartTimeOfDay < utcNowAsMinutesAfterMidnight)
           &&
           (utcNowAsMinutesAfterMidnight < pq.UntilTimeOfDay)))
        {
            available = false;
        }
    }
    return available;
}//end ReportAvailabilityAtThisTime
Private Shared Function ReportAvailabilityAtThisTime(ByVal pq As PrintQueue) As Boolean
    Dim available As Boolean = True
    If pq.StartTimeOfDay <> pq.UntilTimeOfDay Then ' If the printer is not available 24 hours a day
        Dim utcNow As Date = Date.UtcNow
        Dim utcNowAsMinutesAfterMidnight As Int32 = (utcNow.TimeOfDay.Hours * 60) + utcNow.TimeOfDay.Minutes

        ' If now is not within the range of available times . . .
        If Not((pq.StartTimeOfDay < utcNowAsMinutesAfterMidnight) AndAlso (utcNowAsMinutesAfterMidnight < pq.UntilTimeOfDay)) Then
            available = False
        End If
    End If
    Return available
End Function 'end ReportAvailabilityAtThisTime

Метод TimeConverter.ConvertToLocalHumanReadableTime (представленный в приведенном ниже примере кода) не использует методы, представленные в Microsoft .NET Framework, поэтому обсуждение кратко. Метод имеет задачу двойного преобразования: он должен взять целое число, представляющее количество минут после полуночи, и преобразовать его в удобочитаемое время, а затем преобразовать это в местное время. Для этого сначала создаётся объект DateTime, установленный на полночь по UTC, а затем используется метод AddMinutes для добавления минут, переданных в метод. При этом возвращается новый DateTime, указывающий исходное время, переданное методу. Затем метод ToLocalTime преобразует это в локальное время.

private ref class TimeConverter {

internal: 
   static DateTime ConvertToLocalHumanReadableTime (Int32 timeInMinutesAfterUTCMidnight) 
   {
      // Construct a UTC midnight object.
      // Must start with current date so that the local Daylight Savings system, if any, will be taken into account.
      DateTime utcNow = DateTime::UtcNow;
      DateTime utcMidnight = DateTime(utcNow.Year, utcNow.Month, utcNow.Day, 0, 0, 0, DateTimeKind::Utc);

      // Add the minutes passed into the method in order to get the intended UTC time.
      Double minutesAfterUTCMidnight = ((Double)timeInMinutesAfterUTCMidnight);
      DateTime utcTime = utcMidnight.AddMinutes(minutesAfterUTCMidnight);

      // Convert to local time.
      DateTime localTime = utcTime.ToLocalTime();

      return localTime;
   };
};
class TimeConverter
{
    // Convert time as minutes past UTC midnight into human readable time in local time zone.
    internal static DateTime ConvertToLocalHumanReadableTime(Int32 timeInMinutesAfterUTCMidnight)
    {
        // Construct a UTC midnight object.
        // Must start with current date so that the local Daylight Savings system, if any, will be taken into account.
        DateTime utcNow = DateTime.UtcNow;
        DateTime utcMidnight = new DateTime(utcNow.Year, utcNow.Month, utcNow.Day, 0, 0, 0, DateTimeKind.Utc);

        // Add the minutes passed into the method in order to get the intended UTC time.
        Double minutesAfterUTCMidnight = (Double)timeInMinutesAfterUTCMidnight;
        DateTime utcTime = utcMidnight.AddMinutes(minutesAfterUTCMidnight);

        // Convert to local time.
        DateTime localTime = utcTime.ToLocalTime();

        return localTime;
    }// end ConvertToLocalHumanReadableTime
}//end TimeConverter class
Friend Class TimeConverter
    ' Convert time as minutes past UTC midnight into human readable time in local time zone.
    Friend Shared Function ConvertToLocalHumanReadableTime(ByVal timeInMinutesAfterUTCMidnight As Int32) As Date
        ' Construct a UTC midnight object.
        ' Must start with current date so that the local Daylight Savings system, if any, will be taken into account.
        Dim utcNow As Date = Date.UtcNow
        Dim utcMidnight As New Date(utcNow.Year, utcNow.Month, utcNow.Day, 0, 0, 0, DateTimeKind.Utc)

        ' Add the minutes passed into the method in order to get the intended UTC time.
        Dim minutesAfterUTCMidnight As Double = CType(timeInMinutesAfterUTCMidnight, Double)
        Dim utcTime As Date = utcMidnight.AddMinutes(minutesAfterUTCMidnight)

        ' Convert to local time.
        Dim localTime As Date = utcTime.ToLocalTime()

        Return localTime

    End Function ' end ConvertToLocalHumanReadableTime

End Class

См. также