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


Практическое руководство. Определение возможности печати в заданное время суток

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

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

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

Пример

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

Для реализации этой функции существует два следующих основных шага.

  1. Чтение свойств StartTimeOfDay и UntilTimeOfDay из класса PrintQueue для выяснения того, что текущее время находится между значениями, определяемыми этим свойствами.

  2. Чтение свойств StartTimeOfDay и UntilTimeOfDay из класса PrintSystemJobInfo для выяснения того, что текущее время находится между значениями, определяемыми этим свойствами.

Сложности возникают из-за того, что эти свойства не являются объектами 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 со значением true. Если очередь недоступна, этой переменной присваивается значение false.

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

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

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

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

См. также