Показаны сообщения с ярлыком пакет time в Golang. Показать все сообщения
Показаны сообщения с ярлыком пакет time в Golang. Показать все сообщения

пятница, 13 ноября 2020 г.

Go style guides: используйте "time", чтобы управлять временем

Время сложно. К неверным предположениям, которые часто делают относительно времени, относятся следующие.

  1. В сутках 24 часа
  2. В часе 60 минут
  3. В неделе 7 дней
  4. В году 365 дней и другие

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

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

Использование time.Time для моментов времени

Используйте time.Time при работе с моментами времени и методы на time.Time при сравнении, сложении или вычитании времени.

Неудачный вариант:

func isActive(now, start, stop int) bool {
    return start <= now && now < stop
}

Хороший вариант:

func isActive(now, start, stop time.Time) bool {
    return (start.Before(now) || start.Equal(now)) && now.Before(stop)
}

Использовать time.Duration для периодов времени

Используйте time.Duration при работе с периодами времени.

Неудачный вариант:

func poll(delay int) {
    for {
      // ...
      time.Sleep(time.Duration(delay) * time.Millisecond)
    }
}

poll(10) // это были секунды или миллисекунды?

Хороший вариант:

func poll(delay time.Duration) {
    for {
        // ...
        time.Sleep(delay)
    }
}

poll(10*time.Second)

Возвращаясь к примеру добавления 24 часов к моменту времени, метод, который мы используем для добавления времени, зависит от намерения. Если нам нужно то же время дня, но на следующий календарный день, мы должны использовать Time.AddDate. Однако, если мы хотим, чтобы момент времени гарантированно был на 24 часа позже предыдущего, мы должны использовать Time.Add.

newDay := t.AddDate(0 /* years */, 0, /* months */, 1 /* days */)
maybeNewDay := t.Add(24 * time.Hour)

Использование time.Time и time.Duration с внешними системами

По возможности используйте time.Duration и time.Time во взаимодействии с внешними системами. Например:

  • Флаги командной строки: flag поддерживает time.Duration через time.ParseDuration
  • JSON: encoding/json поддерживает кодирование time.Time в виде строки RFC 3339 с помощью метода UnmarshalJSON.
  • SQL: database/sql поддерживает преобразование столбцов DATETIME или TIMESTAMP в time.Time и обратно, если базовый драйвер поддерживает это
  • YAML: gopkg.in/yaml.v2 поддерживает time.Time как строку RFC 3339 и time.Duration через time.ParseDuration.

Если невозможно использовать time.Duration в этих взаимодействиях, используйте int или float64 и включите единицу измерения в имя поля.

Например, поскольку encoding/json не поддерживает time.Duration, единица измерения включается в имя поля.

Неудачный вариант:

// {"interval": 2}
type Config struct {
    Interval int `json:"interval"`
}

Хороший вариант:

// {"intervalMillis": 2000}
type Config struct {
    IntervalMillis int `json:"intervalMillis"`
}

Когда невозможно использовать time.Time в этих взаимодействиях, если не согласована альтернатива, используйте строковые и форматные метки времени, как определено в RFC 3339. Этот формат используется по умолчанию Time.UnmarshalText и доступен для использования во Time.Format и time.Parse по time.RFC3339.

Хотя на практике это обычно не является проблемой, имейте в виду, что пакет "time" не поддерживает синтаксический анализ меток времени с дополнительными секундами (leap seconds), а также не учитывает дополнительные секунды в вычислениях. Если вы сравните два момента времени, разница не будет включать дополнительные секунды, которые могли произойти между этими двумя моментами.


Читайте также:


воскресенье, 2 августа 2020 г.

Пакет time в Golang, тип Timer

type Timer struct {
    C <-chan Time
    // содержит отфильтрованные или неэкспортированные поля
}

Тип Timer представляет одно событие. Когда истекает Timer, текущее время будет отправлено на C, если Timer не был создан AfterFunc. Timer должен быть создан с NewTimer или AfterFunc.

Функция AfterFunc

func AfterFunc(d Duration, f func()) *Timer

AfterFunc ожидает истечения продолжительности d и затем вызывает f в своей собственной goroutine. Он возвращает Timer, который можно использовать для отмены вызова, используя метод Stop.

Функция NewTimer

func NewTimer(d Duration) *Timer

NewTimer создает новый Timer, который будет отправлять текущее время на своем канале, по крайней мере, после продолжительности d.

Пример использования NewTimer

package main

import (
    "fmt"
    "time"
)

func main() {
    fmt.Println("Создаем таймер")
    timer := time.NewTimer(1 * time.Second)
    
    fmt.Println("Ждем таймер")
    <-timer.C

    fmt.Println("Таймер истек")
}

Метод Reset

func (t *Timer) Reset(d Duration) bool

Reset изменяет таймер на истечение после срока действия d. Он возвращает true, если таймер был активен, false, если таймер истек или был остановлен.

Reset должен вызываться только на остановленных или истекших таймерах с опустошенными каналами. Если программа уже получила значение от t.C, таймер, как известно, истек, и канал опустошен, поэтому t.Reset можно использовать напрямую. Однако, если программа еще не получила значение от t.C, таймер должен быть остановлен и - если Stop сообщает, что истек таймер до его остановки - канал явно опустошен:

if !t.Stop() {
    <-t.C
}
t.Reset(d)

Это не должно быть сделано конкурентно с другими приемами от канала Timer.

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

Метод Stop

func (t *Timer) Stop() bool

Stop предотвращает срабатывание Timer. Он возвращает true, если вызов останавливает таймер, false, если таймер уже истек или был остановлен. Stop не закрывает канал, чтобы предотвратить неправильное чтение с канала.

Чтобы убедиться, что канал пуст после вызова Stop, проверьте возвращаемое значение и опустошите канал. Например, если программа еще не получила от t.C:

if !t.Stop() {
    <-t.C
}

Это не может быть сделано одновременно с другими приемами из канала Timer или другими вызовами метода Stop таймера.

Для таймера, созданного с помощью AfterFunc(d, f), если t.Stop возвращает false, то время таймера уже истекло, и функция f была запущена в своей собственной goroutine; Stop не ждет завершения f перед возвратом. Если вызывающий должен знать, завершено ли f, он должен явно координировать с f.


Читайте также:


суббота, 1 августа 2020 г.

Пакет time в Golang, тип Time, методы Sub, Truncate, Round

Метод Sub

func (t Time) Sub(u Time) Duration

Sub возвращает продолжительность t-u. Если результат превышает максимальное (или минимальное) значение, которое может быть сохранено в Duration, будет возвращена максимальная (или минимальная) продолжительность. Чтобы вычислить t-d для продолжительности d, используйте t.Add(-d).

Пример использования Sub

package main

import (
    "fmt"
    "time"
)

func main() {
    start := time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)
    end := time.Date(2000, 1, 1, 12, 0, 0, 0, time.UTC)

    difference := end.Sub(start)
    fmt.Printf("difference = %v\n", difference)

}

Вывод:

difference = 12h0m0s

Метод Truncate

func (t Time) Truncate(d Duration) Time

Truncate возвращает результат округления t до значения, кратного d (начиная с нулевого времени). Если d <= 0, Truncate возвращает t без любых монотонных показаний часов, но в остальном без изменений.

Truncate действует над временем как абсолютной продолжительностью с нулевого времени; он не действует в форме представления времени. Таким образом, Truncate(Hour) может возвращать время с ненулевой минутой, в зависимости от Location времени.

Пример использования Truncate

package main

import (
    "fmt"
    "time"
)

func main() {
    t, _ := time.Parse("2006 Jan 02 15:04:05", "2012 Dec 07 12:15:30.918273645")
    trunc := []time.Duration{
        time.Nanosecond,
        time.Microsecond,
        time.Millisecond,
        time.Second,
        2 * time.Second,
        time.Minute,
        10 * time.Minute,
    }

    for _, d := range trunc {
        fmt.Printf("t.Truncate(%5s) = %s\n", d, 
                   t.Truncate(d).Format("15:04:05.999999999"))
    }
    // Чтобы округлить до последней полуночи 
    // в местном часовом поясе, создаем новую Date.
    midnight := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, time.Local)
    _ = midnight

}

Вывод:

t.Truncate(  1ns) = 12:15:30.918273645
t.Truncate(  1µs) = 12:15:30.918273
t.Truncate(  1ms) = 12:15:30.918
t.Truncate(   1s) = 12:15:30
t.Truncate(   2s) = 12:15:30
t.Truncate( 1m0s) = 12:15:00
t.Truncate(10m0s) = 12:10:00

Метод Round

func (t Time) Round(d Duration) Time

Round возвращает результат округления t до ближайшего кратного d (начиная с нулевого времени). Поведение при округлении для значений на полпути заключается в округлении. Если d <= 0, Round возвращает t без любых монотонных показаний часов, но в остальном без изменений.

Round действует над временем как абсолютной продолжительностью с нулевого времени; он не действует в форме представления времени. Таким образом, Round(Hour) может возвращать время с ненулевой минутой, в зависимости от Location времени.

Отличие от метода Truncate заключается в том, что Truncate возвращает результат округления t до кратного d, а Round возвращает результат округления t до ближайшего кратного d.

Пример использования Round

package main

import (
    "fmt"
    "time"
)

func main() {
    t := time.Date(0, 0, 0, 12, 15, 30, 918273645, time.UTC)
    round := []time.Duration{
        time.Nanosecond,
        time.Microsecond,
        time.Millisecond,
        time.Second,
        2 * time.Second,
        time.Minute,
        10 * time.Minute,
        time.Hour,
    }

    for _, d := range round {
        fmt.Printf("t.Round(%6s) = %s\n", d, t.Round(d).Format("15:04:05.999999999"))
    }
}

Вывод:

t.Round(   1ns) = 12:15:30.918273645
t.Round(   1µs) = 12:15:30.918274
t.Round(   1ms) = 12:15:30.918
t.Round(    1s) = 12:15:31
t.Round(    2s) = 12:15:30
t.Round(  1m0s) = 12:16:00
t.Round( 10m0s) = 12:20:00
t.Round(1h0m0s) = 12:00:00


Читайте также:


Пакет time в Golang, форматирование Time с помощью метода Format

func (t Time) Format(layout string) string

Format возвращает текстовое представление значения времени, отформатированного в соответствии с layout, который определяет формат, показывая, как эталонное время определенное как

Mon Jan 2 15:04:05 -0700 MST 2006

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

Дробная секунда представляется путем добавления точки и нулей в конец секции секунд строки макета, как в "15:04:05.000" для форматирования метки времени с точностью до миллисекунды.

Предопределенные макеты ANSIC, UnixDate, RFC3339 и другие описывают стандартные и удобные представления эталонного времени.

Пример использования Format

package main

import (
    "fmt"
    "time"
)

func main() {
    // Анализируем значение времени из строки 
    // в стандартном формате Unix.
    t, err := time.Parse(time.UnixDate, "Sat Mar  7 11:06:39 PST 2015")
    // Всегда проверяйте ошибки, 
    // даже если они не должны возникать.
    if err != nil { 
        panic(err)
    }

    // Метод String типа time.Time выдает 
    // полезное значение без какого-либо формата.
    // Println проверяет, что передеанное значение 
    // реализует интерфейс Stringer 
    // и вызывает его метод String
    fmt.Println("Формат по умолчанию:", t)

    // Предопределенные константы в пакете
    // реализуют общие макеты.
    fmt.Println("Unix формат:", t.Format(time.UnixDate))

    // Часовой пояс, привязанный к значению времени, 
    // влияет на его вывод.
    fmt.Println("То же самое, но в UTC:", t.UTC().Format(time.UnixDate))

    // Остальная часть этой функции демонстрирует свойства
    // строки макета, используемой в формате.

    // Строка макета, используемая 
    // функцией Parse и методом Format
    // показывает на примере, как должно быть 
    // представлено эталонное время.
    // Подчеркнем, что нужно показать, 
    // как форматируется эталонное время,
    // не время выбора пользователя. 
    // Таким образом, каждая строка макета является
    // представление метки времени,
    //  Jan 2 15:04:05 2006 MST
    // Простой способ запомнить это значение - 
    // оно хранится при представлении
    // в этом порядке значения 
    // (выровненные с элементами выше):
    //    1 2  3  4  5    6  -7
    // Ниже показаны некоторые примеры.

    // Большинство применений Format и Parse 
    // используют строки константного макета, такие как
    // определенные в пакете time, но интерфейс гибкий,
    // как показывают эти примеры.

    // Определяем вспомогательную функцию, 
    // чтобы вывод примеров выглядел красиво.
    do := func(name, layout, want string) {
        got := t.Format(layout)
        if want != got {
            fmt.Printf("ошибка: для %q получено %q; ожидалось %q\n", layout, got, want)
            return
        }
        fmt.Printf("%-25s %q дает %q\n", name, layout, got)
    }

    // Распечатать заголовок в нашем выводе.
    fmt.Printf("\nФорматы:\n\n")

    // Простой стартовый пример.
    do("Базовый", "Mon Jan 2 15:04:05 MST 2006", "Sat Mar 7 11:06:39 PST 2015")

    // Для печати значений фиксированной ширины, 
    // таких как дата, которые могут быть одним или
    // двумя символами (7 против 07), 
    // используйте _ вместо пробела в строке макета.
    // Здесь мы печатаем только день, 
    // который равен 2 в нашей строке макета 
    // и 7 в нашем значении.
    do("Без пробела", "<2>", "<7>")

    // Подчеркивание представляет пробел, 
    // если дата имеет только одну цифру.
    do("Пробелы", "<_2>", "< 7>")

    // "0" указывает заполнение нулями 
    // для однозначных значений.
    do("Нули", "<02>", "<07>")

    // Если значение уже правильной ширины, 
    // заполнение не используется.
    // Например, второе (05 в эталонном времени) 
    // в нашем значении равно 39,
    // так что он не нуждается в заполнении, 
    // а минуты (04, 06) нуждаются.
    do("Подавленное заполнение", "04:05", "06:39")

    // Предопределенная константа Unix 
    // использует подчеркивание для дополнения дня.
    // Сравните с нашим простым начальным примером.
    do("Unix", time.UnixDate, "Sat Mar  7 11:06:39 PST 2015")

    // Час эталонного времени 15 или 3PM. 
    // Макет может выражать это так или иначе,
    // и так как наша значение - утро, 
    // мы должны видеть это как время AM. 
    // Мы показываем оба в одной строке формата. Строчный вид тоже.
    do("AM/PM", "3PM==3pm==15h", "11AM==11am==11h")

    // При разборе, если за значением секунд 
    // следует десятичная точка и несколько цифр, 
    // которые считаются долями секунды, даже если
    // строка макета не представляет доли секунды.
    // Здесь мы добавляем долю секунды 
    // к нашему значению времени, использованному выше.
    t, err = time.Parse(time.UnixDate, "Sat Mar  7 11:06:39.1234 PST 2015")
    if err != nil {
        panic(err)
    }
    // Не отображается в выводе, 
    // если строка макета не содержит
    // представление дробной секунды.
    do("Без дробной части", time.UnixDate, "Sat Mar  7 11:06:39 PST 2015")

    // Дробные секунды могут быть напечатаны 
    // путем добавления серии 0 или 9 после
    // десятичной точки в значении секунд в строке макета.
    // Если цифры макета равны 0, 
    // дробная секунда имеет указанную ширину.
    // Обратите внимание, что выход имеет конечный ноль.
    do("0 для дробной части", "15:04:05.00000", "11:06:39.12340")

    // Если дробь в макете равна 9, конечные нули удаляются.
    do("9 для дробной части", "15:04:05.99999999", "11:06:39.1234")

}

Вывод:

Формат по умолчанию: 2015-03-07 11:06:39 +0000 PST
Unix формат: Sat Mar  7 11:06:39 PST 2015
То же самое, но в UTC: Sat Mar  7 11:06:39 UTC 2015

Форматы:

Базовый                   "Mon Jan 2 15:04:05 MST 2006" дает "Sat Mar 7 11:06:39 PST 2015"
Без пробела               "<2>" дает "<7>"
Пробелы                   "<_2>" дает "< 7>"
Нули                      "<02>" дает "<07>"
Подавленное заполнение    "04:05" дает "06:39"
Unix                      "Mon Jan _2 15:04:05 MST 2006" дает "Sat Mar  7 11:06:39 PST 2015"
AM/PM                     "3PM==3pm==15h" дает "11AM==11am==11h"
Без дробной части         "Mon Jan _2 15:04:05 MST 2006" дает "Sat Mar  7 11:06:39 PST 2015"
0 для дробной части       "15:04:05.00000" дает "11:06:39.12340"
9 для дробной части       "15:04:05.99999999" дает "11:06:39.1234"


Читайте также:


пятница, 31 июля 2020 г.

Пакет time в Golang, тип Time, методы Date, Clock, Day

Метод Date

func (t Time) Date() (year int, month Month, day int)

Date возвращает год, месяц и день, в который происходит t.

Пример использования Date

package main

import (
    "fmt"
    "time"
)

func main() {
    d := time.Date(2000, 2, 1, 12, 30, 0, 0, time.UTC)
    year, month, day := d.Date()

    fmt.Printf("year = %v\n", year)
    fmt.Printf("month = %v\n", month)
    fmt.Printf("day = %v\n", day)

}

Вывод:

year = 2000
month = February
day = 1

Метод Clock

func (t Time) Clock() (hour, min, sec int)

Clock возвращают часы, минуты и секунды в течение дня, указанного в t.

Пример использования Clock

package main

import (
    "fmt"
    "time"
)

func main() {
    d := time.Now()
    hour, min, sec := d.Clock()

    fmt.Printf("hour = %v\n", hour)
    fmt.Printf("min = %v\n", min)
    fmt.Printf("sec = %v\n", sec)

}

Вывод:

hour = 19
min = 22
sec = 27

Метод Day

func (t Time) Day() int

Day возвращает день месяца, указанного в t.

Пример использования Day

package main

import (
    "fmt"
    "time"
)

func main() {
    d := time.Date(2000, 2, 1, 12, 30, 0, 0, time.UTC)
    day := d.Day()

    fmt.Printf("day = %v\n", day)

}

Вывод:

day = 1


Читайте также:


четверг, 30 июля 2020 г.

Пакет time в Golang, тип Time, методы After, Before, Equal, IsZero

Метод After

func (t Time) After(u Time) bool

After сообщает, является ли момент времени t после u.

Пример использования After

package main

import (
    "fmt"
    "time"
)

func main() {
    year2000 := time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)
    year3000 := time.Date(3000, 1, 1, 0, 0, 0, 0, time.UTC)

    isYear3000AfterYear2000 := year3000.After(year2000) // True
    isYear2000AfterYear3000 := year2000.After(year3000) // False

    fmt.Printf("year3000.After(year2000) = %v\n", isYear3000AfterYear2000)
    fmt.Printf("year2000.After(year3000) = %v\n", isYear2000AfterYear3000)

}

Вывод:

year3000.After(year2000) = true
year2000.After(year3000) = false

Метод Before

func (t Time) Before(u Time) bool

Before сообщает, находится ли момент времени t перед u.

Пример использования Before

package main

import (
    "fmt"
    "time"
)

func main() {
    year2000 := time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)
    year3000 := time.Date(3000, 1, 1, 0, 0, 0, 0, time.UTC)

    isYear2000BeforeYear3000 := year2000.Before(year3000) // True
    isYear3000BeforeYear2000 := year3000.Before(year2000) // False

    fmt.Printf("year2000.Before(year3000) = %v\n", isYear2000BeforeYear3000)
    fmt.Printf("year3000.Before(year2000) = %v\n", isYear3000BeforeYear2000)

}

Вывод:

year2000.Before(year3000) = true
year3000.Before(year2000) = false

Метод Equal

func (t Time) Equal(u Time) bool

Equal сообщает, представляют ли t и u один и тот же момент времени. Два времени могут быть равны, даже если они находятся в разных местах. Например, 6:00 +0200 and 4:00 UTC равны. О ловушках использования == со значениями Time; большая часть кода должна использовать вместо этого Equal.

Пример использования Equal

package main

import (
    "fmt"
    "time"
)

func main() {
    secondsEastOfUTC := int((8 * time.Hour).Seconds())
    beijing := time.FixedZone("Beijing Time", secondsEastOfUTC)

    // В отличие от оператора равенства (==), Equal знает, 
    // что d1 и d2 являются одним и тем же моментом, 
    // но в разных часовых поясах.
    d1 := time.Date(2000, 2, 1, 12, 30, 0, 0, time.UTC)
    d2 := time.Date(2000, 2, 1, 20, 30, 0, 0, beijing)

    datesEqualUsingEqualOperator := d1 == d2
    datesEqualUsingFunction := d1.Equal(d2)

    fmt.Printf("datesEqualUsingEqualOperator = %v\n", datesEqualUsingEqualOperator)
    fmt.Printf("datesEqualUsingFunction = %v\n", datesEqualUsingFunction)

}

Вывод:

datesEqualUsingEqualOperator = false
datesEqualUsingFunction = true

Метод IsZero

func (t Time) IsZero() bool

IsZero сообщает, представляет ли t нулевой момент времени, January 1, year 1, 00:00:00 UTC.

Пример использования IsZero

package main

import (
    "fmt"
    "time"
)

func main() {
    t := time.Date(1, time.January, 1, 00, 0, 0, 0, time.UTC)
    fmt.Printf("Это нулевое значение Time %s\n", t.UTC())
    fmt.Printf("Верно? %v\n", t.IsZero())
}

Вывод:

Это нулевое значение Time 0001-01-01 00:00:00 +0000 UTC
Верно? true


Читайте также:


среда, 29 июля 2020 г.

Пакет time в Golang, тип Time, методы Add, AddDate

Метод Add

func (t Time) Add(d Duration) Time

Add возвращает время t+d.

Пример использования Add

package main

import (
    "fmt"
    "time"
)

func main() {
    start := time.Date(2009, 1, 1, 12, 0, 0, 0, time.UTC)
    afterTenSeconds := start.Add(time.Second * 10)
    afterTenMinutes := start.Add(time.Minute * 10)
    afterTenHours := start.Add(time.Hour * 10)
    afterTenDays := start.Add(time.Hour * 24 * 10)

    fmt.Printf("start = %v\n", start)
    fmt.Printf("start.Add(time.Second * 10) = %v\n", afterTenSeconds)
    fmt.Printf("start.Add(time.Minute * 10) = %v\n", afterTenMinutes)
    fmt.Printf("start.Add(time.Hour * 10) = %v\n", afterTenHours)
    fmt.Printf("start.Add(time.Hour * 24 * 10) = %v\n", afterTenDays)

}

Вывод:

start = 2009-01-01 12:00:00 +0000 UTC
start.Add(time.Second * 10) = 2009-01-01 12:00:10 +0000 UTC
start.Add(time.Minute * 10) = 2009-01-01 12:10:00 +0000 UTC
start.Add(time.Hour * 10) = 2009-01-01 22:00:00 +0000 UTC
start.Add(time.Hour * 24 * 10) = 2009-01-11 12:00:00 +0000 UTC

Метод AddDate

func (t Time) AddDate(years int, months int, days int) Time

AddDate возвращает время, соответствующее добавлению заданного количества лет, месяцев и дней к t. Например, AddDate(-1, 2, 3), примененный к January 1, 2011, возвращает March 4, 2010.

AddDate нормализует свой результат так же, как Date, например, добавление одного месяца к October 31 приводит к December 1, нормализованной форме для November 31.

Пример использования AddDate

package main

import (
    "fmt"
    "time"
)

func main() {
    start := time.Date(2009, 1, 1, 0, 0, 0, 0, time.UTC)
    oneDayLater := start.AddDate(0, 0, 1)
    oneMonthLater := start.AddDate(0, 1, 0)
    oneYearLater := start.AddDate(1, 0, 0)

    fmt.Printf("oneDayLater: start.AddDate(0, 0, 1) = %v\n", oneDayLater)
    fmt.Printf("oneMonthLater: start.AddDate(0, 1, 0) = %v\n", oneMonthLater)
    fmt.Printf("oneYearLater: start.AddDate(1, 0, 0) = %v\n", oneYearLater)

}

Вывод:

oneDayLater: start.AddDate(0, 0, 1) = 2009-01-02 00:00:00 +0000 UTC
oneMonthLater: start.AddDate(0, 1, 0) = 2009-02-01 00:00:00 +0000 UTC
oneYearLater: start.AddDate(1, 0, 0) = 2010-01-01 00:00:00 +0000 UTC


Читайте также:


Пакет time в Golang, функции Parse, ParseInLocation

Функция Parse

func Parse(layout, value string) (Time, error)

Parse разбирает отформатированную строку и возвращает значение времени, которое она представляет. layout определяет формат, показывая, как эталонное время, определенное как

Mon Jan 2 15:04:05 -0700 MST 2006

будет интерпретироваться, если бы это было значение; layout служит примером формата ввода. Такая же интерпретация будет затем сделана для входной строки.

Предопределенные макеты ANSIC, UnixDate, RFC3339 и другие описывают стандартные и удобные представления эталонного времени.

Элементы, опущенные в value, предполагаются равными нулю или, если ноль невозможен, равны единице, поэтому анализ "3:04pm" возвращает время, соответствующее Jan 1, year 0, 15:04:00 UTC (обратите внимание, что, поскольку год 0, это время до нулевого Time). Годы должны быть в диапазоне 0000..9999. День недели проверяется на синтаксис, но в противном случае он игнорируется.

Для макетов с указанием двузначного года 06 значение NN >= 69 будет рассматриваться как 19NN, а значение NN < 69 будет рассматриваться как 20NN.

При отсутствии индикатора часового пояса Parse возвращает время в UTC.

При анализе времени со смещением зоны, например -0700, если смещение соответствует часовому поясу, используемому текущим местоположением (Local), то Parse использует это местоположение и зону в возвращенном времени. В противном случае он записывает время, как находящееся в сфабрикованном месте, со временем, зафиксированным в заданном смещении зоны.

При разборе времени с аббревиатурой зоны, такой как MST, если аббревиатура зоны имеет определенное смещение в текущем местоположении, то это смещение используется. Аббревиатура зоны "UTC" распознается как UTC независимо от местоположения. Если аббревиатура зоны неизвестна, Parse записывает время, как находящееся в сфабрикованном месте с данной аббревиатурой зоны и нулевым смещением. Этот выбор означает, что такое время может быть проанализировано и переформатировано с той же компоновкой без потерь, но точный момент, используемый в представлении, будет отличаться фактическим смещением зоны. Чтобы избежать таких проблем, предпочитайте временные макеты, которые используют числовое смещение зоны, или используйте ParseInLocation.

Пример использования Parse

package main

import (
    "fmt"
    "time"
)

func main() {
    // longForm показывает в качестве примера, 
    // как эталонное время 
    // будет представлено в желаемом макете.
    const longForm = "Jan 2, 2006 at 3:04pm (MST)"
    t, _ := time.Parse(longForm, "Feb 3, 2013 at 7:54pm (PST)")
    fmt.Println(t)

    // shortForm это другой способ 
    // как будет представлено эталонное время
    // в нужном макете; нет часового пояса.
    // Примечание: без явной зоны возвращает время в UTC.
    const shortForm = "2006-Jan-02"
    t, _ = time.Parse(shortForm, "2013-Feb-03")
    fmt.Println(t)

    // Некоторые допустимые макеты являются 
    // недопустимыми значениями времени 
    // из-за спецификаторов формата
    // например _ для пробела и Z для информации о зоне.
    // Например, макет RFC3339 2006-01-02T15:04:05Z07:00
    // содержит как Z, так и смещение часового пояса 
    // для обработки обеих допустимых опций:
    // 2006-01-02T15:04:05Z
    // 2006-01-02T15:04:05+07:00
    t, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z")
    fmt.Println(t)
    t, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05+07:00")
    fmt.Println(t)
    _, err := time.Parse(time.RFC3339, time.RFC3339)
    fmt.Println("error", err) 
    // Возвращает ошибку, 
    // поскольку макет не является допустимым значением
    
}

Вывод:

2013-02-03 19:54:00 +0000 PST
2013-02-03 00:00:00 +0000 UTC
2006-01-02 15:04:05 +0000 UTC
2006-01-02 15:04:05 +0700 +0700
error parsing time "2006-01-02T15:04:05Z07:00": extra text: 07:00

Функция ParseInLocation

func ParseInLocation(layout, value string, loc *Location) (Time, error)

ParseInLocation похож на Parse, но отличается двумя важными способами. Во-первых, при отсутствии информации о часовом поясе Parse интерпретирует время как UTC; ParseInLocation интерпретирует время как в переданном местоположении. Во-вторых, когда задано смещение или сокращение зоны, Parse пытается сопоставить его с Local местоположением; ParseInLocation использует переданное местоположение.

Пример использования ParseInLocation

package main

import (
    "fmt"
    "time"
)

func main() {
    loc, _ := time.LoadLocation("Europe/Berlin")

    // Будет искать имя CEST в часовом поясе Europe/Berlin.
    const longForm = "Jan 2, 2006 at 3:04pm (MST)"
    t, _ := time.ParseInLocation(longForm, "Jul 9, 2012 at 5:02am (CEST)", loc)
    fmt.Println(t)

    // Примечание: 
    // без явной зоны возвращает время в указанном location.
    const shortForm = "2006-Jan-02"
    t, _ = time.ParseInLocation(shortForm, "2012-Jul-09", loc)
    fmt.Println(t)

}

Вывод:

2012-07-09 05:02:00 +0200 CEST
2012-07-09 00:00:00 +0200 CEST


Читайте также:


вторник, 28 июля 2020 г.

Пакет time в Golang, функции Date, Now, Unix

Функция Date

func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time

Date возвращает Time, соответствующее

yyyy-mm-dd hh:mm:ss + nsec nanoseconds

в соответствующей зоне для этого времени в данном месте.

Значения month, day, hour, min, sec, и nsec могут выходить за пределы своих обычных диапазонов и будут нормализованы во время преобразования. Например, October 32 конвертируется в November 1.

Переход на летнее время пропускает или повторяет время. Например, в Соединенных Штатах 13 марта 2011 г. 2:15 никогда не происходило, а 6 ноября 2011 г. 1:15 происходило дважды. В таких случаях выбор часового пояса и, следовательно, времени не является четко определенным. Date возвращает время, которое является правильным в одной из двух зон, участвующих в переходе, но не гарантирует, в какой именно.

Date паникует, если loc - nil.

Пример использования Date

package main

import (
    "fmt"
    "time"
)

func main() {
    t := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
    fmt.Printf("Go запущен %s\n", t.Local())
}

Вывод

Go запущен 2009-11-10 23:00:00 +0000 UTC

Функция Now

func Now() Time

Now возвращает текущее местное время.

Пример использования Now

package main

import (
    "fmt"
    "time"
)

func main() {
    t := time.Now()
    fmt.Printf("Сейчас %s\n", t)
}

Вывод

Сейчас 2020-07-28 09:27:51.223683882 +0500 +05 m=+0.000052967

Функция Unix

func Unix(sec int64, nsec int64) Time

Unix возвращает местное время, соответствующее указанному времени Unix, sec секунд и nsec наносекунд, с 1 января 1970 года UTC. Допустимо передавать nsec вне диапазона [0, 999999999]. Не все значения sec имеют соответствующее значение времени. Одним из таких значений является 1<<63-1 (наибольшее значение int64).

Пример использования Unix

package main

import (
    "fmt"
    "time"
)

func main() {
    t := time.Now().Unix()
    fmt.Printf("Текущий timestamp %d\n", t)
}

Вывод

Текущий timestamp 1596910715


Читайте также:


Пакет time в Golang, тип Time

type Time struct {
    // содержит отфильтрованные или неэкспортированные поля
}

Time представляет собой момент времени с наносекундной точностью.

Программы, использующие времена, обычно должны хранить и передавать их как значения, а не как указатели. То есть переменные времени и поля структуры должны иметь тип time.Time, а не *time.Time.

Значение Time может использоваться несколькими программами одновременно, за исключением того, что методы GobDecode, UnmarshalBinary, UnmarshalJSON и UnmarshalText не являются безопасными для конкурентности.

Моменты Time можно сравнить с помощью методов Before, After и Equal. Метод Sub вычитает два момента, создавая Duration. Метод Add добавляет Time и Duration, создавая Time.

Нулевым значением типа Time является January 1, year 1, 00:00:00.000000000 UTC. Поскольку это время вряд ли подходит на практике, метод IsZero предоставляет простой способ обнаружения времени, которое не было явно инициализировано.

Каждое время связывает с ним Location (местоположение), к которому обращаются при расчете формы представления времени, таких методах как Format, Hour и Year. Методы Local, UTC и In возвращают Time с определенным местоположением. Изменение местоположения таким образом изменяет только представление; оно не меняет момент времени, который будет обозначен, и, следовательно, не влияет на вычисления со временем.

Представления значения Time, сохраненного методами GobEncode, MarshalBinary, MarshalJSON и MarshalText, хранят смещение Time.Location, но не имя местоположения. Поэтому они теряют информацию о переходе на летнее время.

В дополнение к требуемым показаниям "настенных часов", Time может содержать дополнительное показание монотонных часов текущего процесса, чтобы обеспечить дополнительную точность для сравнения или вычитания.

Обратите внимание, что оператор Go == сравнивает не только момент времени, но и местоположение и показания монотонных часов. Следовательно, значения времени не должны использоваться в качестве ключей карты или базы данных без предварительной гарантии того, что для всех значений было установлено одинаковое местоположение, что может быть достигнуто с помощью метода UTC или Local, и что монотонное считывание часов было удалено установкой t = t.Round(0). В общем, предпочитайте t.Equal(u), а не t == u, так как t.Equal использует наиболее точное из доступных сравнений и правильно обрабатывает случай, когда только один из его аргументов имеет монотонное чтение часов.


Читайте также:


воскресенье, 26 июля 2020 г.

Пакет time в Golang, тип Ticker

Ticker содержит канал, который поставляет "тики" часов с интервалами.

type Ticker struct {
    C <-chan Time // Канал, по которому доставляются тики.
    // содержит отфильтрованные или неэкспортированные поля
}

Функция NewTicker

func NewTicker(d Duration) *Ticker

NewTicker возвращает новый Ticker, содержащий канал, который будет отправлять время с периодом, заданным аргументом продолжительности. Он корректирует интервалы или сбрасывает тики, чтобы восполнить медленные приемники. Продолжительность d должна быть больше нуля; если нет, NewTicker будет паниковать. Остановите тикер, чтобы освободить связанные ресурсы.

Пример использования Ticker

package main

import (
    "fmt"
    "time"
)

func main() {
    ticker := time.NewTicker(time.Second)
    defer ticker.Stop()
    done := make(chan bool)
    go func() {
        time.Sleep(10 * time.Second)
        done <- true
    }()
    for {
        select {
        case <-done:
            fmt.Println("Готово!")
            return
        case t := <-ticker.C:
            fmt.Println("Текущее время: ", t)
        }
    }
}

Вывод:

Текущее время:  2020-07-26 22:03:37.925067 +0500 +05 m=+1.008175801
Текущее время:  2020-07-26 22:03:38.9258884 +0500 +05 m=+2.008997201
Текущее время:  2020-07-26 22:03:39.9282 +0500 +05 m=+3.011308801
Текущее время:  2020-07-26 22:03:40.9290208 +0500 +05 m=+4.012129601
Текущее время:  2020-07-26 22:03:41.9298391 +0500 +05 m=+5.012947901
Текущее время:  2020-07-26 22:03:42.9313325 +0500 +05 m=+6.014441301
Текущее время:  2020-07-26 22:03:43.9330786 +0500 +05 m=+7.016187401
Текущее время:  2020-07-26 22:03:44.9390601 +0500 +05 m=+8.022168901
Текущее время:  2020-07-26 22:03:45.9320627 +0500 +05 m=+9.015171501
Текущее время:  2020-07-26 22:03:46.941485 +0500 +05 m=+10.024593801
Готово!

Метод Stop

func (t *Ticker) Stop()

Stop отключает тикер. После остановки никакие тики больше не будут отправляться. Stop не закрывает канал, чтобы предотвратить чтение из канала конкурентной goroutine ошибочного "тика".


Читайте также:


Пакет time в Golang, тип Month

Month указывает месяц года (January = 1, February = 2, March = 3, ...).

type Month int

const (
    January Month = 1 + iota
    February
    March
    April
    May
    June
    July
    August
    September
    October
    November
    December
)

Пример использования Month:

package main

import (
    "fmt"
    "time"
)

func main() {
    _, month, day := time.Now().Date()
    if month == time.November && day == 10 {
        fmt.Println("День рождения Go!")
    }   
    fmt.Println("Текущий месяц:", month)    
    fmt.Println("Текущий день:", day )
}

Вывод:

День рождения Go!
Текущий месяц: November
Текущий день: 10

Метод String

func (m Month) String() string

String возвращает английское название месяца ("January", "February", ...).


Читайте также:


суббота, 25 июля 2020 г.

Пакет time в Golang, функции возвращающие Location

Функция FixedZone

func FixedZone(name string, offset int) *Location

FixedZone возвращает местоположение, которое всегда использует заданное имя зоны и смещение (в секундах к востоку от UTC).

Пример использования FixedZone:

package main

import (
    "fmt"
    "time"
)

func main() {
    loc := time.FixedZone("UTC-8", -8*60*60)
    t := time.Date(2009, time.November, 10, 23, 0, 0, 0, 
                   loc)
    fmt.Println("Время:", t.Format(time.RFC822))
}

Вывод:

Время: 10 Nov 09 23:00 UTC-8

Функция LoadLocation

func LoadLocation(name string) (*Location, error)

LoadLocation возвращает Location с заданным именем.

Если имя "" или "UTC", LoadLocation возвращает UTC. Если имя "Local", LoadLocation возвращает Local.

В противном случае имя считается именем местоположения, соответствующим файлу в базе данных часового пояса IANA, например "America/New_York".

База данных часовых поясов, необходимая для LoadLocation, может присутствовать не во всех системах, особенно в не-Unix системах. LoadLocation просматривает каталог или несжатый zip-файл с именем переменной среды ZONEINFO, если таковой имеется, затем просматривает известные места установки в системах Unix и, наконец, просматривает файл $GOROOT/lib/time/zoneinfo.zip.

Пример использования LoadLocation:

package main

import (
    "fmt"
    "time"
)

func main() {
    location, err := time.LoadLocation("America/Los_Angeles")
    if err != nil {
        panic(err)
    }

    timeInUTC := time.Date(2018, 8, 30, 12, 0, 0, 0, 
                           time.UTC)
    fmt.Println(timeInUTC)
    fmt.Println(timeInUTC.In(location))
}

Вывод:

2018-08-30 12:00:00 +0000 UTC
2018-08-30 05:00:00 -0700 PDT


Читайте также:


Пакет time в Golang, тип Location

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

type Location struct {
    // содержит отфильтрованные или неэкспортированные поля
}

Local представляет местный часовой пояс системы. В системах Unix Local обращается к переменной окружения TZ, чтобы найти часовой пояс для использования. Отсутствие TZ означает использование системного значения по умолчанию /etc/localtime. TZ="" означает использовать UTC. TZ="foo" означает использовать файл foo в системном каталоге часовых поясов.

var Local *Location = &localLoc

UTC представляет собой всемирное координированное время (UTC, Universal Coordinated Time).

var UTC *Location = &utcLoc

Пример использования Location

package main

import (
    "fmt"
    "time"
)

func main() {
    // В Китае нет летнего времени. 
    // Китай использует 
    // фиксированное 8-часовое смещение от UTC.
    secondsEastOfUTC := int((8 * time.Hour).Seconds())
    beijing := time.FixedZone("Beijing Time", 
                              secondsEastOfUTC)

    // Если в системе есть база данных часовых поясов, 
    // можно загрузить местоположение из нее, например:
    // newYork, err := time.LoadLocation("America/New_York")

    // Создание времени требует местоположения (location). 
    // Распространенными местоположениями 
    // являются time.Local и time.UTC.
    timeInUTC := time.Date(2009, 1, 1, 12, 0, 0, 0, 
                           time.UTC)
    sameTimeInBeijing := time.Date(2009, 1, 1, 20, 0, 0, 0, 
                                   beijing)

    // Хотя время по UTC составляет 1200, 
    // а время по Пекину - 2000, 
    // Пекин на 8 часов вперед, 
    // поэтому две даты фактически представляют 
    // один и тот же момент.
    timesAreEqual := timeInUTC.Equal(sameTimeInBeijing)
    fmt.Println(timesAreEqual) 
    // печатает true
}


Читайте также:


пятница, 24 июля 2020 г.

Пакет time в Golang, методы типа Duration

Метод Hours

func (d Duration) Hours() float64

Hours возвращает продолжительность в виде количества часов числом с плавающей запятой.

Пример использования Hours

package main

import (
    "fmt"
    "time"
)

func main() {
    h, _ := time.ParseDuration("4h30m")
    fmt.Printf("Осталось %.1f часа до полудня.", h.Hours())
}

Вывод:

Осталось 4.5 часа до полудня.

Метод Microseconds

func (d Duration) Microseconds() int64

Microseconds возвращает длительность в виде целого числа микросекунд.

Пример использования Microseconds

package main

import (
    "fmt"
    "time"
)

func main() {
    u, _ := time.ParseDuration("1s")
    fmt.Printf("Одна секунда это %d микросекунд.\n", 
               u.Microseconds())
}

Вывод:

Одна секунда это 1000000 микросекунд.

Метод Milliseconds

func (d Duration) Milliseconds() int64

Milliseconds возвращает длительность в виде целого числа миллисекунд.

Пример использования Milliseconds

package main

import (
    "fmt"
    "time"
)

func main() {
    u, _ := time.ParseDuration("1s")
    fmt.Printf("Одна секунда это %d миллисекунд.\n", 
               u.Microseconds())
}

Вывод:

Одна секунда это 1000 миллисекунд.

Методы Minutes

func (d Duration) Minutes() float64

Minutes возвращает продолжительность в виде количества минут числом с плавающей точкой.

Пример использования Minutes

package main

import (
    "fmt"
    "time"
)

func main() {
    m, _ := time.ParseDuration("1h30m")
    fmt.Printf("Фильм длится %.0f минут.", m.Minutes())
}

Вывод:

Фильм длится 90 минут.

Метод Nanoseconds

func (d Duration) Nanoseconds() int64

Nanoseconds возвращает длительность в виде целого числа наносекунд.

Пример использования Nanoseconds

package main

import (
    "fmt"
    "time"
)

func main() {
    u, _ := time.ParseDuration("1µs")
    fmt.Printf("Одна микросекунда это %d наносекунд.\n", 
               u.Nanoseconds())
}

Вывод:

Одна микросекунда это 1000 наносекунд.

Метод Round (с версии Go 1.9)

func (d Duration) Round(m Duration) Duration

Round возвращает результат округления d до ближайшего кратного m. Поведение при округлении для значений на полпути заключается в округлении от нуля. Если результат превышает максимальное (или минимальное) значение, которое может быть сохранено в Duration, Round возвращает максимальную (или минимальную) продолжительность. Если m <= 0, Round возвращает d без изменений.

Пример использования Round

package main

import (
    "fmt"
    "time"
)

func main() {
    d, err := time.ParseDuration("1h15m30.918273645s")
    if err != nil {
        panic(err)
    }

    round := []time.Duration{
        time.Nanosecond,
        time.Microsecond,
        time.Millisecond,
        time.Second,
        2 * time.Second,
        time.Minute,
        10 * time.Minute,
        time.Hour,
    }

    for _, r := range round {
        fmt.Printf("d.Round(%6s) = %s\n", 
                   r, d.Round(r).String())
    }
}

Вывод:

d.Round(   1ns) = 1h15m30.918273645s
d.Round(   1µs) = 1h15m30.918274s
d.Round(   1ms) = 1h15m30.918s
d.Round(    1s) = 1h15m31s
d.Round(    2s) = 1h15m30s
d.Round(  1m0s) = 1h16m0s
d.Round( 10m0s) = 1h20m0s
d.Round(1h0m0s) = 1h0m0s

Метод Seconds

func (d Duration) Seconds() float64

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

Пример использования Seconds

package main

import (
    "fmt"
    "time"
)

func main() {
    m, _ := time.ParseDuration("1m30s")
    fmt.Printf("Полторы минуты это %.0f секунд.", 
               m.Seconds())
}

Вывод:

Полторы минуты это 90 секунд.

Метод String

func (d Duration) String() string

String возвращает строку, представляющую продолжительность в форме "72h3m0.5s". Ведущие нулевые элементы опущены. В качестве особого случая для форматов длительностью менее одной секунды используется меньшая единица измерения (милли-, микро- или наносекунды), чтобы гарантировать, что начальная цифра не равна нулю. Нулевая длительность форматируется как 0s.

Пример использования String

package main

import (
    "fmt"
    "time"
)

func main() {
    t1 := time.Date(2016, time.August, 15, 0, 0, 0, 0, time.UTC)
    t2 := time.Date(2017, time.February, 16, 0, 0, 0, 0, time.UTC)
    fmt.Println(t2.Sub(t1).String())
}

Вывод:

4440h0m0s

Метод Truncate (с версии Go 1.9)

func (d Duration) Truncate(m Duration) Duration

Truncate возвращает результат округления d до нуля, кратный m. Если m <= 0, Truncate возвращает d без изменений.

Пример использования Truncate

package main

import (
    "fmt"
    "time"
)

func main() {
    d, err := time.ParseDuration("1h15m30.918273645s")
    if err != nil {
        panic(err)
    }

    trunc := []time.Duration{
        time.Nanosecond,
        time.Microsecond,
        time.Millisecond,
        time.Second,
        2 * time.Second,
        time.Minute,
        10 * time.Minute,
        time.Hour,
    }

    for _, t := range trunc {
        fmt.Printf("d.Truncate(%6s) = %s\n", 
                   t, d.Truncate(t).String())
    }
}

Вывод:

d.Truncate(   1ns) = 1h15m30.918273645s
d.Truncate(   1µs) = 1h15m30.918273s
d.Truncate(   1ms) = 1h15m30.918s
d.Truncate(    1s) = 1h15m30s
d.Truncate(    2s) = 1h15m30s
d.Truncate(  1m0s) = 1h15m0s
d.Truncate( 10m0s) = 1h10m0s
d.Truncate(1h0m0s) = 1h0m0s


Читайте также:


Пакет time в Golang, тип Duration и функции работающие с ним

type Duration int64

Duration представляет прошедшее время между двумя моментами в виде подсчета int64 наносекунд. Представление ограничивает наибольшую представляемую продолжительность приблизительно 290 годами.

package main

import (
    "fmt"
    "time"
)

func expensiveCall() {
    time.Sleep(3 * time.Second)
}

func main() {
    t0 := time.Now()
    expensiveCall()
    t1 := time.Now()
    fmt.Printf("Вызов занимает %v для выполнения.\n", 
               t1.Sub(t0))
}

Вывод:

Вызов занимает 3.000154165s для выполнения.

Функция ParseDuration

func ParseDuration(s string) (Duration, error)

ParseDuration анализирует строку продолжительности. Строка продолжительности - это, возможно, последовательность десятичных чисел со знаком, каждое из которых содержит необязательную дробь и суффикс единицы, например "300ms", "-1.5h" или "2h45m". Допустимые единицы времени: "ns", "us" (или "µs"), "ms", "s", "m", "h".

Пример использования ParseDuration

package main

import (
    "fmt"
    "time"
)

func main() {
    hours, _ := time.ParseDuration("10h")
    complex, _ := time.ParseDuration("1h10m10s")
    micro, _ := time.ParseDuration("1µs")
    // Функция также принимает некорректный, 
    // но принятый префикс для micro.
    micro2, _ := time.ParseDuration("1us")

    fmt.Println(hours)
    fmt.Println(complex)
    fmt.Printf("%.0f секунд в %v.\n", 
               complex.Seconds(), complex)
    fmt.Printf("%d наносекунд в %v.\n", 
               micro.Nanoseconds(), micro)
    fmt.Printf("%6.2e секунд в %v.\n", 
               micro2.Seconds(), micro)
}

Вывод:

10h0m0s
1h10m10s
4210 секунд в 1h10m10s.
1000 наносекунд в 1µs.
1.00e-06 секунд в 1µs.

Функция Since

func Since(t Time) Duration

Since возвращает время, прошедшее с момента t. Это сокращение для time.Now().Sub(t).

Пример использования Since

package main

import (
    "fmt"
    "time"
)

func main() {
    t := time.Now()
    time.Sleep(3 * time.Second)
    fmt.Printf("Прошло %v \n", time.Since(t))
}

Вывод:

Прошло 3s 

Функция Until (с версии Go 1.8)

func Until(t Time) Duration

Until возвращает продолжительность до t. Это сокращение для t.Sub(time.Now()).

Пример использования Until

package main

import (
    "fmt"
    "time"
)

func main() {
    t := time.Now()
    time.Sleep(3 * time.Second)
    fmt.Printf("Осталось %v \n", time.Until(t))
}

Вывод:

Осталось -3s 


Читайте также:


четверг, 23 июля 2020 г.

Пакет time в Golang, функции After, Sleep, Tick

Функция After

func After(d Duration) <-chan Time

After ожидает истечения продолжительности d, а затем отправляет текущее время по возвращаемому каналу. Это эквивалентно NewTimer(d).C. Базовый Timer не восстанавливается сборщиком мусора, пока таймер не истекет. Если важна эффективность, используйте вместо нее NewTimer и вызовите Timer.Stop, если таймер больше не нужен.

Привет использования After

package main

import (
    "fmt"
    "time"
)

var c chan int

func handle(int) {}

func main() {
    select {
    case m := <-c:
        handle(m)
    case <-time.After(3 * time.Second):
        fmt.Println("timed out")
    }
}

Вывод (после 3 секунд от запуска):

timed out

Функция Sleep

func Sleep(d Duration)

Sleep приостанавливает текущую goroutine как минимум на время d. Отрицательная или нулевая продолжительность приводит к немедленному возвращению Sleep.

Пример использования Sleep

package main

import (
    "fmt"
    "time"
)

func main() {
    fmt.Println("Старт")
    time.Sleep(3000 * time.Millisecond)
    fmt.Println("Финиш")
}

Вывод:

Старт
Финиш

Функция Tick

func Tick(d Duration) <-chan Time

Tick - это удобная оболочка для NewTicker, предоставляющая доступ только к тиковому каналу. Хотя Tick полезен для клиентов, которым нет необходимости выключать Ticker, имейте в виду, что без способа выключить его базовый Ticker не может быть восстановлен сборщиком мусора; это "утечки". В отличие от NewTicker, Tick вернет nil, если d <= 0.

Пример использования Tick

package main

import (
    "fmt"
    "time"
)

func statusUpdate() string { return "" }

func main() {
    c := time.Tick(5 * time.Second)
    for next := range c {
        fmt.Printf("%v %s\n", next, statusUpdate())
    }
}

Вывод:

2020-07-23 19:54:46.764984441 +0500 +05 m=+5.000241495 
2020-07-23 19:54:51.764984609 +0500 +05 m=+10.000241638 
2020-07-23 19:54:56.76481557 +0500 +05 m=+15.000072594 
2020-07-23 19:55:01.765103332 +0500 +05 m=+20.000360383 
... // и так каждые 5 секунд


Читайте также:


вторник, 21 июля 2020 г.

Пакет time в Golang, константы

Здесь представлены предопределенные макеты для использования в Time.Format и time.Parse. Эталонное время, используемое в макетах, это конкретное время:

Mon Jan 2 15:04:05 MST 2006

это время Unix 1136239445. Поскольку MST - это GMT-0700, отсчет времени можно рассматривать как

01/02 03:04:05PM '06 -0700

Чтобы определить свой собственный формат, запишите, как будет выглядеть отформатированное эталонное время; посмотрите значения таких констант, как ANSIC, StampMicro или Kitchen, например. Модель должна продемонстрировать, как выглядит эталонное время, чтобы методы Format и Parse могли применять одно и то же преобразование к общему значению времени.

Некоторые допустимые макеты являются недопустимыми значениями времени для time.Parse из-за форматов, таких как _ для заполнения пробелов и Z для информации о зоне.

В строке формата подчеркивание _ представляет пробел, который может быть заменен цифрой, если следующее число (день) имеет две цифры; для совместимости с фиксированными форматами времени Unix.

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

Числовой формат смещения часового пояса выглядит следующим образом:

-0700  ±hhmm
-07:00 ±hh:mm
-07    ±hh

Замена знака в формате буквой Z вызывает поведение печати по стандарту ISO 8601 вместо смещения для зоны UTC. Таким образом:

Z0700  Z or ±hhmm
Z07:00 Z or ±hh:mm
Z07    Z or ±hh

Распознанные форматы дня недели - "Mon" и "Monday". Распознаются форматы месяцев: "Jan" и "January".

Форматы 2, _2 и 02 - это не дополненные, дополненные пробелами и дополненные нулями дни месяца. Форматы __2 и 002 - трехсимвольный день года с пробелами и нулями; нет незаполненного формата дня года.

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

Обратите внимание, что форматы RFC822, RFC850 и RFC1123 должны применяться только к местному времени. Применение их к времени UTC будет использовать "UTC" как сокращение часового пояса, в то время как строго говоря, эти RFC требуют использования "GMT" в этом случае. В общем случае RFC1123Z следует использовать вместо RFC1123 для серверов, которые настаивают на этом формате, а RFC3339 следует отдавать предпочтение новым протоколам. RFC3339, RFC822, RFC822Z, RFC1123 и RFC1123Z полезны для форматирования; при использовании с time.Parse они не принимают все форматы времени, разрешенные RFC. Формат RFC3339Nano удаляет завершающие нули из поля секунд и, следовательно, может не правильно сортировать после форматирования.

const (
    ANSIC       = "Mon Jan _2 15:04:05 2006"
    UnixDate    = "Mon Jan _2 15:04:05 MST 2006"
    RubyDate    = "Mon Jan 02 15:04:05 -0700 2006"
    RFC822      = "02 Jan 06 15:04 MST"
    RFC822Z     = "02 Jan 06 15:04 -0700" // RFC822 с числовой зоной
    RFC850      = "Monday, 02-Jan-06 15:04:05 MST"
    RFC1123     = "Mon, 02 Jan 2006 15:04:05 MST"
    RFC1123Z    = "Mon, 02 Jan 2006 15:04:05 -0700" // RFC1123 с числовой зоной
    RFC3339     = "2006-01-02T15:04:05Z07:00"
    RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
    Kitchen     = "3:04PM"
    // Удобные метки времени.
    Stamp      = "Jan _2 15:04:05"
    StampMilli = "Jan _2 15:04:05.000"
    StampMicro = "Jan _2 15:04:05.000000"
    StampNano  = "Jan _2 15:04:05.000000000"
)

Не существует определения единиц Day или больше, чтобы избежать путаницы при переходе на часовой пояс при переходе на летнее время.

Чтобы подсчитать количество единиц в Duration, разделите:

second := time.Second
fmt.Print(int64(second/time.Millisecond)) // печатает 1000

Чтобы преобразовать целое число единиц в Duration, умножьте:

seconds := 10
fmt.Print(time.Duration(seconds)*time.Second) // печатает 10s

const (
    Nanosecond  Duration = 1
    Microsecond          = 1000 * Nanosecond
    Millisecond          = 1000 * Microsecond
    Second               = 1000 * Millisecond
    Minute               = 60 * Second
    Hour                 = 60 * Minute
)


Читайте также:


Пакет time в Golang, монотонные часы

Пакет time обеспечивает функциональность для измерения и отображения времени.

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

Монотонные часы

Операционные системы предоставляют как "настенные часы", которые могут быть изменены для синхронизации часов, так и "монотонные часы", которые не могут быть изменены для синхронизации часов. Общее правило заключается в том, что настенные часы предназначены для определения времени, а монотонные часы - для измерения времени. Вместо того, чтобы разделять API, в этом пакете Time, возвращаемое time.Now содержит как чтение настенных часов, так и чтение монотонных часов; в более поздних операциях с указанием времени используется считывание настенных часов, а в более поздних операциях измерения времени, в частности сравнения и вычитания, используется монотонное считывание часов.

Например, этот код всегда вычисляет положительное прошедшее время, равное приблизительно 20 миллисекундам, даже если настенные часы меняются во время рассчитываемой операции:

start := time.Now()
... операция, которая занимает 20 миллисекунд ...
t := time.Now()
elapsed := t.Sub(start)

Другие идиомы, такие как time.Since(start), time.Until(deadline), и time.Now().Before(deadline), одинаково устойчивы к сбросам настенных часов.

В оставшейся части этого поста приводятся точные сведения о том, как в операциях используются монотонные часы.

Время, возвращаемое time.Now содержит монотонное чтение часов. Если время t имеет монотонные показания часов, t.Add добавляет одинаковую длительность как к настенным часам, так и к показаниям монотонных часов, чтобы вычислить результат. Поскольку t.AddDate(y, m, d), t.Round(d) и t.Truncate(d) являются вычислениями времени по настенным часам, они всегда удаляют любые монотонные показания часов из своих результатов. Поскольку t.In, t.Local и t.UTC используются для их влияния на интерпретацию настенного времени, они также удаляют любые монотонные показания часов из своих результатов. Канонический способ снять монотонное чтение часов - использовать t = t.Round(0).

Если времена t и u содержат монотонные показания часов, операции t.After(u), t.Before(u), t.Equal(u) и t.Sub(u) выполняются с использованием только монотонных показаний часов, игнорируя показания настенных часов. Если ни t, ни u не содержат монотонных показаний часов, эти операции сводятся к использованию показаний настенных часов.

В некоторых системах монотонные часы остановятся, если компьютер перейдет в спящий режим. В такой системе t.Sub(u) может не точно отражать фактическое время, прошедшее между t и u.

Поскольку монотонное чтение часов не имеет смысла вне текущего процесса, сериализованные формы, сгенерированные t.GobEncode, t.MarshalBinary, t.MarshalJSON и t.MarshalText, опускают монотонное чтение часов, и t.Format не предоставляет для него никакого формата. Аналогично, конструкторы time.Date, time.Parse, time.ParseInLocation и time.Unix, а также демаршалеры t.GobDecode, t.UnmarshalBinary. t.UnmarshalJSON и t.UnmarshalText всегда создают времена без монотонного чтения часов.

Обратите внимание, что оператор Go == сравнивает не только момент времени, но и местоположение и показания монотонных часов.

Для отладки результат t.String включает монотонное чтение часов, если оно присутствует. Если t != u из-за различных монотонных показаний часов, эта разница будет видна при печати t.String() и u.String().


Читайте также:


понедельник, 25 мая 2020 г.

Время не число в Golang

Почему не компилируется?

n := 100
time.Sleep(n * time.Millisecond)

invalid operation: n * time.Millisecond (mismatched types int and time.Duration)

Ответ

В Go нет смешивания числовых типов. Вы можете умножить time.Duration только на

  • другой time.Duration или
  • нетипизированную целочисленную константу.

Вот три правильных примера.

var n time.Duration = 100
time.Sleep(n * time.Millisecond)

const n = 100
time.Sleep(n * time.Millisecond)

time.Sleep(100 * time.Millisecond)

Смотрите нетипизированные числовые константы без ограничений для деталей о типизированных и нетипизированных целочисленных и константах с плавающей запятой и их пределах.


Читайте также: