time.Time упрощает работу с датами и временем в Go, и даже входит в стандартную библиотеку! Однако в большинстве случаев структура time.Time{} использует более 24 байта памяти, и я сталкивался с ситуациями, когда мне нужно было хранить в памяти миллионы байтов, но все, что мне действительно было нужно, была дата UTC! Go-TinyDate решает эту проблему, используя всего 4 байта памяти.

Звезда Github! https://github.com/lane-c-wagner/go-tinydate

Как?

Давайте посмотрим на структуру time.Time:

type Time struct {
	wall uint64 // 8 bytes
	ext  int64 // b bytes
	loc *Location // 8 bytes if not nil, plus location memory
}

type Location struct {
	name string // unlimited
	zone []zone // unlimited
	tx   []zoneTrans // unlimited
	cacheStart int64 // 8 bytes
	cacheEnd   int64 // 8 bytes
	cacheZone  *zone // 8 bytes if not nil, plus zone
}

type zone struct {
	name   string // unlimited
	offset int    // 4-8 bytes depending on OS
	isDST  bool   // 1 bit
}

type zoneTrans struct {
	when         int64 // 8 bytes
	index        uint8 // 1 byte
	isstd, isutc bool  // 1 bit
}


Как видите, в зависимости от того, как установлен TimeZone, может быть достаточно много памяти, выделенной только для хранения time.Time. Даже если местоположение не задано, нижняя граница по-прежнему составляет 16 байт.

В отличие от tinydate.TinyDate{}:

type TinyDate struct {
	year uint16 // 2 byte
	month uint8 // 1 byte
	day uint8 // 1 byte
}

Всего 4 байта! Мы отказываемся от возможности отслеживать что-то более конкретное, чем дата, но часто это все, что нам нужно.

Быстрый старт

Создайте дату и добавьте к ней:

package main

import (
    tinydate "github.com/lane-c-wagner/go-tinydate"
)

func main(){
    td, err := tinydate.New(2020, 04, 3)
	if err != nil {
		fmt.Println(err.Error())
    }
    
    td = td.Add(time.Hour * 48)
    fmt.Println(td)
    // prints 2020-04-05
}

Или переведите время на крошечную дату и обратно:

newTinydate, err := FromTime(time.Now())
if err != nil{
    fmt.Println(err.Error())
}
convertedTime := newTinydate.ToTime()

Когда я должен использовать это?

Как говорится в Readme TinyDate, если вы не ограничены в ресурсах, лучше придерживаться стандартного time.Time. Но следующие ситуации могут быть вескими причинами для перехода на TinyDate:

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

Почему нет часовых поясов?

Главная причина? Часовые пояса занимают больше всего памяти в структуре time.Time, однако рекомендуется обычно хранить даты и время только в формате UTC. TinyDate остается крошечным, всегда сохраняя даты в формате UTC, но по-прежнему дает возможность вычислять даты в других часовых поясах с помощью таких методов, как ParseInLocation, FromTime и ToTime.

API

API tinydate.Tinydate во многом повторяет интерфейс time.Time. Отсутствуют только те методы, которые не имеют смысла без часового пояса или внутридневной поддержки. Проверьте годок для справки: https://godoc.org/github.com/lane-c-wagner/go-tinydate

Спасибо за чтение

Напишите мне в твиттере @wagslane, если у вас есть какие-либо вопросы или комментарии.

Переулок на Dev.to: wagslane

Если вам понравился пакет, поставьте ему звезду на Github

Пост Я написал Go-TinyDate, The Missing Golang Date Package впервые появился на Qvault.