Golang에서 반복 처리 날짜

21176 단어 Gorruletech

Golang에서 반복 처리 날짜


안녕하십니까? 이번에 Golang에서 역법을 처리할 기회가 생겨서 저는 그것을 필기로 남겼습니다.
달력을 자유롭게 조종하고 골랑으로 점치기 앱을 쉽게 만들고 싶다.

Golang 시간


Golang에는 표준 프로그램 라이브러리가 있습니다. 표준 시간도 사용할 수 있고 시간 형식도 지원합니다.
예를 들어, 현재의 시간은 아래와 같이 기술할 수 있다.
package main

import (
	"fmt"
	"time"
)

func main() {
    fmt.Println(time.Now())
}
https://play.golang.org/p/CzmUKIlJCRU
그렇다면 여기서 얻은 현재 시점을 기점으로 일정 날짜를 반복적으로 얻었을 때는 어떻게 해야 할까.

RRLE 정보


실제로 RFC 2445는 중복 설정을 데이터로 저장하는 데 유용한 형태를 지정합니다.
Internet Calendaring and Scheduling Core Object Specification
http://www.ietf.org/rfc/rfc2445.txt
이번엔 이 RRLE로 중복된 날짜를 얻자.
Golang에는 RRLE을 사용할 수 있는 여러 개의 프로그램 라이브러리가 있습니다.
이번에는 지허브에 비해 스타 수가 많은 rrule-go를 사용하고 싶다.
https://github.com/teambition/rrule-go
예를 들어, RRLE는 현재 날짜와 시간에서 일주일의 날짜와 시간을 5번 반복해서 가져오려면 다음과 같이 정의할 수 있습니다.
"DTSTART: 현재 날짜 및 시간\nFREQ = WEEEKLY, INTERVAL = 1; COUNT=5"
또한rrule-go 이 RRLE를 문자열로 교부하면 데이터를 얻을 수 있습니다.
package main

import (
	"fmt"
	"time"

	"github.com/teambition/rrule-go"
)

func main() {
	var timesetter string
	timesetter = time.Now().Format("20060102T150405Z")
	rruleInstance := "DTSTART:" + timesetter + "\n" + "FREQ=WEEKLY;INTERVAL=1;COUNT=5"
	s, err := rrule.StrToRRule(rruleInstance)
	if err != nil {
		fmt.Println("Rrule error",err)
	}
	fmt.Println(s.All())
}
https://play.golang.org/p/1jfzbKJrih2
이렇게 하면 매우 치밀하게 묘사할 수 있다.
RRLE의 표현 방법이 많아서 따라잡을 수 없기 때문에 여기에 위의 예에 남기지만 실제 사용할 때는 용도에 따라 RRLE 문자열을 만들어야 하기 때문에 한 문자열의 함수를 따로 정의하는 것이 편하다고 생각합니다.
예를 들어 RRLE에서 UNTIL을 추출하려면 다음과 같은 느낌이 든다.
package main

import (
	"fmt"
	"time"

	"github.com/teambition/rrule-go"
)

func GetUntil(startData time.Time, endData time.Time, rruleData *string, exdateData *string) (time.Time, error) {
	var rruleInstance string
	var err error
	timeSetter := startData.Format("20060102T150405Z")
	if rruleData == nil {
		return endTimeData, err
	}
	rruleInstance = fmt.Sprintf("DTSTART:%s\nRRULE:%s", timeSetter, *rruleData)
	if exdateData != nil {
		rruleInstance = fmt.Sprintf("%s\nEXDATE:%s", rruleInstance, *exdateData)
	}
	RRule, err := rrule.StrToRRuleSet(rruleInstance)
	if err != nil {
		return endData, err
	}
	Until := RRule.All()[len(RRule.All())-1]
	return Until, err
}

실제로 해보세요.


오랜만에 와서 간단한 구체적인 예로 인간의 생물 리듬으로 계산해 보자.
RRLE를 사용하여 주기를 간단하게 계산할 수 있습니다.
  • 신체(Physical)23일주기: 체력, 내구력, 저항력, 지구력, 에너지, 용기 등
  • 감정(Sensitivity)28일주기: 감정, 기분, 신경, 직각, 분위기, 감수성, 반사력, 창조력 등
  • 지성(Intelliectual)33일주기: 지능, 사고력, 기억력, 분석력, 판단력, 집중력, 구성력 등
  • \sin(\frac{2\pi t}{T})
    출전: CASIO
    https://keisan.casio.jp/exec/system/1231994137 T는 각 주기를 가리킨다.
    또한 t에 대한 정의는 다음과 같습니다.
    t = baseday - birthday
    Unixtime 을 사용하여 실제 날짜 차를 계산합니다.
    왜냐하면 Golang의 표준 Unixtime은 초니까.
    24\times 60\times 60 = 86400
    이 86400을 아래의 Unixtime로 나누는 것이 좋다.
    t := float64(baseday.Unix()/86400 - birthday.Unix()/86400)
    
    설치 후 아래와 같습니다.
    package main
    
    import (
    	"fmt"
    	"math"
    	"time"
    
    	"github.com/teambition/rrule-go"
    )
    
    func biorhythm(startData time.Time, count int32, t float64) {
    	timeSetter := startData.Format("20060102T150405Z")
    	rrulePhysical := fmt.Sprintf("DTSTART:%s\nFREQ=DAILY;INTERVAL=23;COUNT=%d", timeSetter, count)
    	rruleSensitivity := fmt.Sprintf("DTSTART:%s\nFREQ=DAILY;INTERVAL=28;COUNT=%d", timeSetter, count)
    	rruleIntellectual := fmt.Sprintf("DTSTART:%s\nFREQ=DAILY;INTERVAL=33;COUNT=%d", timeSetter, count)
    	P, _ := rrule.StrToRRule(rrulePhysical)
    	S, _ := rrule.StrToRRule(rruleSensitivity)
    	I, _ := rrule.StrToRRule(rruleIntellectual)
    
    	fmt.Printf("Physical:     ")
    	fmt.Printf("sin(2πt/T)=%f", math.Sin((t*2*math.Pi)/23))
    	fmt.Println(P.All())
    
    	fmt.Printf("Sensitivity:  ")
    	fmt.Printf("sin(2πt/T)=%f", math.Sin((t*2*math.Pi)/28))
    	fmt.Println(S.All())
    
    	fmt.Printf("Intellectual: ")
    	fmt.Printf("sin(2πt/T)=%f", math.Sin((t*2*math.Pi)/33))
    	fmt.Println(I.All())
    }
    
    func main() {
    	birthday := // ? = time.Time型の誕生日をセット
    	baseday :=  // ? = time.Time型の基準日をセット
    	fmt.Println(birthday,baseday)
    	t := float64(baseday.Unix()/86400 - birthday.Unix()/86400)
    	biorhythm(birthday, 10, t)
    }
    
    https://play.golang.org/p/VOQl20-x9Cc
    플레이 그라운드에서 한번 해볼게요.
    2020-11-07 23:00:00 +0000 UTC m=+346896000.000000001
    2020-11-14 23:00:00 +0000 UTC m=+347500800.000000001
    설정되었습니다.
    이런 형태로 RRLE를 사용하면 언어화되기 때문에 간단한 표현으로 주기를 계산할 수 있다.

    최후


    생물 리듬에 관해서는 통계학적으로 의미 있는 데이터를 얻지 못했으니 주의하세요.
    하지만 가설이라도 연예계에 자주 등장한다.
    Golang의 프로그램 라이브러리 등에 대해 특성, 용법을 충분히 이해한 토대에서 이 도구를 어떻게 사용하는지는 사용자에 달려 있다.
    참고 자료
    「Internet Calendaring and Scheduling Core Object Specification」 http://www.ietf.org/rfc/rfc2445.txt
    「rrule-go」 https://github.com/teambition/rrule-go
    "생물 규칙"https://ja.wikipedia.org/wiki/바이오 리듬
    "생물 규칙의 계산"https://keisan.casio.jp/exec/system/1231994137

    좋은 웹페이지 즐겨찾기