Форматированиедаты и времени
В 5.4.7 вы уже сталкивались с форматированием чисел. Форматирование нужно для того, чтобы представить информацию в удобном для пользователя виде. Осуществляет форматирование функция Format. У нее два аргумента (параметра): первый – что форматировать, второй – как форматировать. Функция возвращает значение типа String.
Готовые форматы. Рассмотрим программу:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim t As DateTime = #8/10/2004 4:42:39 PM#
WriteLine(Format(t, "General Date")) '10.08.2004 16:42:39
WriteLine(Format(t, "Long Date")) '10 Август 2004 г.
WriteLine(Format(t, "Short Date")) '10.08.2004
WriteLine(Format(t, "Long Time")) '16:42:39
WriteLine(Format(t, "Short Time")) '16:42
WriteLine(Format(t, "f")) '10 Август 2004 г. 16:42
WriteLine(Format(t, "F")) '10 Август 2004 г. 16:42:39
WriteLine(Format(t, "g")) '10.08.2004 16:42
WriteLine(Format(t, "y")) 'Август 2004 г.
End Sub
Пояснения: Здесь первый аргумент – t. Второй – строка. Содержание строки определяет вид результата. То, что печатают операторы программы, написано в комментариях.
Форматы, определяемые программистом. Мы рассмотрели здесь наиболее популярные из готовых форматов, которые нам предоставляет VB. Но форматы можно конструировать и самому. Рассмотрим программу:
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim t As DateTime = #8/5/2004 7:02:09 PM#
WriteLine(Format(t, "fff")) '000 - доли секунды (тысячные, потому что 3 буквы f)
WriteLine(Format(t, "%s")) '9 - секунды
WriteLine(Format(t, "ss")) '09 - секунды
WriteLine(Format(t, "%m")) '2 - минуты
WriteLine(Format(t, "mm")) '02 - минуты
WriteLine(Format(t, "%h")) '7 - часы до и после полудня
WriteLine(Format(t, "hh")) '07 - часы до и после полудня
WriteLine(Format(t, "%H")) '19 - часы
WriteLine(Format(#3:02:09 AM#, "HH")) '03 - часы
WriteLine(Format(t, "%d")) '5 - число месяца
WriteLine(Format(t, "dd")) '05 - число месяца
WriteLine(Format(t, "ddd")) 'Чт - день недели
WriteLine(Format(t, "dddd")) 'четверг - день недели
WriteLine(Format(t, "%M")) '8 - месяц
WriteLine(Format(t, "MM")) '08 - месяц
WriteLine(Format(t, "MMM")) 'авг - месяц
WriteLine(Format(t, "MMMM")) 'Август - месяц
WriteLine(Format(t, "%y")) '4 - год
WriteLine(Format(t, "yy")) '04 - год
WriteLine(Format(t, "yyyy")) '2004 - год
End Sub
Пояснения: В комментариях вы видите результаты работы операторов программы с пояснениями. Знак процента употребляется тогда, когда в кавычках стоит один единственный символ форматирования, чтобы не спутать его с символом готового формата.
Мы рассмотрели здесь, как выделять из переменной нужные нам элементарные части даты или времени. Теперь посмотрим, как их комбинировать, чтобы получить вразумительную строку:
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
Dim t As DateTime = #8/5/2004 7:02:09 PM#
WriteLine(Format(t, "dd-MM-yy")) '05-08-04
WriteLine(Format(t, "d MMM yyyy")) '5 авг 2004
WriteLine(Format(t, "Настал yyyy год.")) 'Настал 2004 год.
WriteLine(Format(t, "d/MM/yy")) '5.08.04
WriteLine(Format(t, "HH:m:ss")) '19:2:09
WriteLine(Format(t, "HH,m.ss")) '19,2.09
WriteLine(Format(t, "HH часов d MMM")) '19 часов 5 авг
WriteLine(Format(t, "Было %h часов вечера и m минуты")) 'Было 7 часов вечера и 2 минуты
End Sub
Пояснения: Если мы при разделении элементов даты пользуемся косой чертой, то в результате разделителем становится символ, на который настроена Windows (в России – точка, в США – косая черта). То же самое можно сказать о двоеточии для разделения элементов времени суток. Но мы можем для разделения сравнительно свободно пользоваться и другими символами: черточками, пробелами, точками, запятыми, буквами русского алфавита и др.
Задание 76.
Напишите программу, которая, ничего у вас не спрашивая, печатает, какое число будет через 52 недели.
Задание 77.
Напишите программу, которая, спросив у вас дату рождения и не спрашивая, какое сегодня число, печатает, сколько секунд вы живете на белом свете.
Задание 78.
Напишите программу, которая, спросив у вас дату рождения и не спрашивая, какое сегодня число и был ли у вас в этом году день рождения, печатает, сколько дней вам осталось до следующего дня рождения.
Задание 79.
Я знаю, что високосных годов ученым не хватает. Поэтому, не то где-то раз в много лет вклинивается лишний високосный год, не то иногда где-то в каком-то месяце бывает лишний день. Не знаю. Может быть VB подскажет?
Таймер
Суть работы таймера. Создайте новый проект. Возьмите из Toolbox элемент управления Timer и поместите его на форму. Однако, подобно элементу управления Меню, таймер расположится не на форме, а под ней, на дизайнере компонентов. Установите его свойство Enabeled в True, а свойство Interval равным 10000. Сделайте двойной щелчок по таймеру. В появившуюся заготовку процедуры впишите одну строчку:
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Debug.WriteLine("Процедура сработала")
End Sub
Запустите проект. Подождите немного. Через 10 секунд в окне Output появится строчка "Процедура сработала". Еще через 10 секунд появится такая же строчка, через 10 секунд еще одна, и так далее.
Если бы мы установили Interval равным 5000, то строчки появлялись бы каждые 5 с, а если равным 500, то – каждые 0,5 с. Получается, что свойство Interval задает промежуток времени в миллисекундах (мс – тысячных долях секунды).
Вывод: Таймер Timer1 – объект, вся работа которого заключается в том, чтобы через каждые Interval миллисекунд создавать событие (импульс), которое запускает процедуру Timer1_Tick.
Цикл без цикла. В процедуре Timer1_Tick мы можем написать все, что угодно. Например:
Dim i As Long = 1
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Debug.WriteLine("Процедура сработала " & i & "-й раз")
i = i + 1
End Sub
Установите Interval в 1000. Запустите проект. Вы увидите через каждую секунду возникающие строчки:
Процедура сработала 1-й раз
Процедура сработала 2-й раз
Процедура сработала 3-й раз
Процедура сработала 4-й раз
Мы видим, что у нас заработал цикл, несмотря на то, что операторов цикла мы не писали! Чуть позже вы догадаетесь, как вовремя делать выход из цикла.
Свойство таймера Enabled. Установим свойство таймера Enabled (по-русски – «в рабочем состоянии») в False. Запустим проект. Никаких строк не появляется. Значит таймер выдает импульсы только тогда, когда свойство Enabled установлено в True.
Добавим в проект две кнопки и к ним две процедуры:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Timer1.Enabled = True
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Timer1.Enabled = False
End Sub
Запустите проект. Вы увидите, что новые строчки появляются только после щелчка по первой кнопке, а после щелчка по второй прекращают появляться.
«Холостые» импульсы. Что будет, если процедура Timer1_Tick еще не успела закончить работу, а от таймера уже пришел новый импульс? Проверим. Установим Interval равным 100, то есть импульсы от таймера должны посылаться примерно 10 раз в секунду. Напишем процедуру Timer1_Tick, которая очень долго работает:
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Debug.WriteLine("Процедура таймера начала работу")
For i = 1 To 200000000 : Next
Debug.WriteLine("Процедура таймера закончила работу")
End Sub
Здесь долго работает пустой цикл
For i = 1 To 200000000 : Next
Несмотря на то, что делать ему нечего (тело у цикла отсутствует), у него много времени уходит на то, чтобы просто досчитать до 200 миллионов. На моем компьютере это занимает секунд пять, на вашем, наверное, по-другому. Это неважно, а важно то, что за эти пять секунд в процедуру врежется порядка 50 импульсов от таймера. И все как об стену горох – процедура на них не реагирует. Пока не завершит свою работу, как положено, оператором End Sub. После этого первый же следующий импульс, которому повезло, снова ее запускает. Вы увидите, что на экране не спеша, где-то раз в пять секунд появляется очередная пара строчек.
Точность таймера. Проведя эксперименты на компьютере Celeron 400, я обнаружил, что таймер выдает импульсы от интервала 10 мс и выше. То есть минимальное время между импульсами = 10 мс. Задавать интервал меньше 10 бесполезно. Однако, это все-таки гораздо лучше, чем в VB 6.0, где это время равнялось 1/18 доле секунды.
Задание 80.
Запрограммируйте с помощью таймера печать чисел от 100 до 110 через 1 секунду.
Несколько таймеров. Таймеров в проекте может быть несколько. Все они работают независимо друг от друга и каждый имеет свою собственную процедуру, которая реагирует только на его импульсы.
Поместите в проект два таймера. Интервал первого задайте равным 1000, второго – 3000. Вот программа:
Dim i As Long = 1
Dim j As Long = 1
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Debug.WriteLine("Первый таймер сработал " & i & "-й раз")
i = i + 1
End Sub
Private Sub Timer2_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer2.Tick
Debug.WriteLine("Второй таймер сработал " & j & "-й раз")
j = j + 1
End Sub
А вот результаты:
Первый таймер сработал 1-й раз
Второй таймер сработал 1-й раз
Первый таймер сработал 2-й раз
Первый таймер сработал 3-й раз
Первый таймер сработал 4-й раз
Второй таймер сработал 2-й раз
Первый таймер сработал 5-й раз
Первый таймер сработал 6-й раз
Первый таймер сработал 7-й раз
Второй таймер сработал 3-й раз
Как видите, второй таймер срабатывает в 3 раза реже первого.
Перечисления
С перечислениями мы с вами сталкивались не раз. Каждый раз под перечислением понимался список значений какого-нибудь свойства или параметра, или чего-нибудь другого. Например, в 12.3.6мы использовали перечисление RotateFlipType в качестве параметра метода. У этого перечисления 16 значений, из которых можно выбирать любое.
Все перечисления, с которыми мы сталкивались, были созданы заранее профессиональными программистами, включены ими в библиотеку классов .NET Framework и достались нам готовыми к употреблению. Нам осталось только с удобством выбирать значения из всплывающего списка. Однако в реальном программировании часто встречаются ситуации, когда необходимо иметь перечисление, еще никем не созданное.
Пример 1. Пусть вам хотелось бы с удобством пользоваться списком своих любимых футбольных команд:
Real, MU, Вперед, Milan
VB позволяет вам самому создать такое (и вообще, какое угодно) перечисление и пользоваться им. Вот что нужно для этого сделать.
Сначала в верхней части окна кода, вне процедур, пишем такой текст:
Enum Мои_команды
Real
MU
Вперед
Milan
End Enum
Это не процедура, хоть и похожа. Слово Enumозначает, что это перечисление. Мы придумали ему имя Мои_команды. Слова End Enum означают конец перечисления.
Это и не переменная. Вы не можете написать
Мои_команды = Вперед
То, что мы создали, это новый тип. Тип Мои_команды. Впервые мы не просто пользуемся типом, а создаем тип.
Чтобы извлечь выгоду из этого типа и воспользоваться перечислением, мы должны создать переменную данного типа. Делается это обычным образом:
Dim Команда As Мои_команды
Переменная Команда имеет право принимать только одно из четырех значений, перечисленных в объявлении типа.
Пользоваться этим перечислением так же удобно, как и остальными. Например, когда вы наберете текст
Команда =
VB любезно распахнет перед вами список из всех четырех значений перечисления. Правда, перед каждым значением он поставит точку и имя типа, что кажется несколько громоздким. Получится вот что:
Команда = Мои_команды.Milan
Теперь вы можете как угодно работать с переменной. Например, так:
If Команда = Мои_команды.Real Then MsgBox("Это не команда, а сборная мира!")
Пример 2. Все значения перечисления пронумерованы, начиная с нуля. Поэтому при работе с ними удобно применять операторы цикла. Проиллюстрирую работу с переменными перечислимого типа на примере перечисления дней недели:
Public Class Form1
Inherits System.Windows.Forms.Form
Windows Form Designer generated code
Enum Дни
понедельник
вторник
среда
четверг
пятница
суббота
воскресенье
End Enum
Dim День As Дни
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
День = 0
Debug.WriteLine(День) 'понедельник
День = 1
Debug.WriteLine(День) 'вторник
День = Дни.понедельник
Debug.WriteLine(День) 'понедельник
День = День + 2
Debug.WriteLine(День) 'среда
День = Дни.среда
Do Until День = Дни.воскресенье
День = День + 1
Debug.WriteLine(День) 'четверг пятница суббота воскресенье
Loop
For День = Дни.вторник To Дни.четверг
Debug.WriteLine(День) 'вторник среда четверг
Next
For День = Дни.воскресенье To Дни.понедельник Step -2
Debug.WriteLine(День) 'воскресенье пятница среда понедельник
Next
End Sub
End Class
Пояснения: То, что напечатают операторы этой программы, вы видите в комментариях. Поскольку все значения перечисления пронумерованы, то, например, все равно, как написать:
День = 1
или
День = Дни.вторник
Пример 3. В этом примере вы увидите, как можно анализировать с пользой для дела переменные перечислимого типа. Предполагается, что, как в предыдущем примере, определены тип Дни и переменная День.
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
День = InputBox("Введите номер дня недели")
Select Case День - 1 'Чтобы понедельник был не нулевым, а первым
Case Дни.понедельник To Дни.среда
MsgBox("Начало недели")
Case Дни.четверг, Дни.пятница
MsgBox("Середина недели")
Case Дни.суббота, Дни.воскресенье
MsgBox("Отдых")
Case Is > Дни.воскресенье, Is < Дни.понедельник
MsgBox("Таких дней не бывает")
End Select
End Sub
Пояснения: Обратите внимание, что вводить день недели привычным образом буквами просто так не удастся, так как информация, вводимая в текстовое поле окна InputBox имеет тип String, который автоматически не преобразуется в перечислимый. Поэтому я выбрал ввод номера дня недели.
Настоящую пользу из собственных перечислений вы начнете извлекать в проекте «Будильник-секундомер» и когда изучите массивы.