Skip to content

Commit

Permalink
Merge pull request #8 from goark/julian-day-number
Browse files Browse the repository at this point in the history
Add Julian Day Number package
  • Loading branch information
spiegel-im-spiegel authored May 2, 2022
2 parents 8c25bd2 + d47217e commit 29b5324
Show file tree
Hide file tree
Showing 8 changed files with 337 additions and 58 deletions.
82 changes: 37 additions & 45 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,52 +15,44 @@ on:
- cron: '0 20 * * 0'

jobs:
analyze:
name: Analyze
CodeQL-Build:
# CodeQL runs on ubuntu-latest, windows-latest, and macos-latest
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
# Override automatic language detection by changing the below list
# Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
language: ['go']
# Learn more...
# https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
permissions:
# required for all workflows
security-events: write

steps:
- name: Checkout repository
uses: actions/checkout@v2
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
fetch-depth: 2

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main

# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1

# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# only required for workflows in private repositories
actions: read
contents: read

# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language

#- run: |
# make bootstrap
# make release

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
steps:
- name: Checkout repository
uses: actions/checkout@v3

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
# Override language selection by uncommenting this and choosing your languages
with:
languages: go

# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below).
- name: Autobuild
uses: github/codeql-action/autobuild@v2

# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl

# ✏️ If the Autobuild fails above, remove it and uncomment the following
# three lines and modify them (or add more) to build your code if your
# project uses a compiled language

#- run: |
# make bootstrap
# make release

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
28 changes: 25 additions & 3 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,43 @@ on:
branches:
- master
pull_request:

permissions:
contents: read
# Optional: allow read access to pull request. Use with `only-new-issues` option.
# pull-requests: read
jobs:
golangci:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
- uses: actions/setup-go@v3
with:
go-version: ^1.18
- uses: actions/checkout@v3
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
# Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version
version: latest

# Optional: working directory, useful for monorepos
# working-directory: somedir

# Optional: golangci-lint command line arguments.
args: --enable gosec

# Optional: show only new issues if it's a pull request. The default value is `false`.
# only-new-issues: true

# Optional: if set to true then the all caching functionality will be complete disabled,
# takes precedence over all other caching options.
# skip-cache: true

# Optional: if set to true then the action don't cache or restore ~/go/pkg.
# skip-pkg-cache: true

# Optional: if set to true then the action don't cache or restore ~/.cache/go-build.
# skip-build-cache: true
- name: testing
run: go test -shuffle on ./...
45 changes: 45 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,50 @@ Year 2021 is 辛丑
Day 2021-07-28 is 丁丑
```

### ユリウス日

```go
//go:build run
// +build run

package main

import (
"flag"
"fmt"
"os"

"github.com/goark/koyomi"
"github.com/goark/koyomi/jdn"
)

func main() {
flag.Parse()
args := flag.Args()
if len(args) < 1 {
fmt.Fprintln(os.Stderr, os.ErrInvalid)
return
}
for _, s := range args {
t, err := koyomi.DateFrom(s)
if err != nil {
fmt.Fprintln(os.Stderr, err)
continue
}
j := jdn.GetJDN(t.Time)
fmt.Printf("Julian Day Number of %v is %v\n", t.Format("2006-01-02"), j)
}
}
```

これを実行すると以下のような結果になります。

```
$ go run sample/sample4.go 2022-01-01
$ go run sample/sample4.go 2022-01-01
Julian Day Number of 2022-01-01 is 2459580
```

## Modules Requirement Graph

[![dependency.png](./dependency.png)](./dependency.png)
Expand All @@ -231,6 +275,7 @@ Day 2021-07-28 is 丁丑

- [国立天文台 天文情報センター 暦計算室](https://eco.mtk.nao.ac.jp/koyomi/)
- [今月のこよみ powered by Google Calendar - 国立天文台暦計算室](https://eco.mtk.nao.ac.jp/koyomi/cande/calendar.html)
- [ユリウス日について - 国立天文台暦計算室](https://eco.mtk.nao.ac.jp/koyomi/topics/html/topics2023_1.html)
- [日本の暦情報を取得するパッケージを作ってみた — リリース情報 | text.Baldanders.info](https://text.baldanders.info/release/2020/05/koyomi/)

[Go 言語]: https://golang.org/ "The Go Programming Language"
Expand Down
99 changes: 99 additions & 0 deletions jdn/jdn.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package jdn

import (
"math/big"
"time"
)

// GetJD returns Julian Day from time.Time.
func GetJD(dt time.Time) *big.Rat {
dt = dt.In(time.UTC)
y := intRat(int64(dt.Year()))
m := int64(dt.Month())
d := int64(dt.Day())
k := floorRat(quoInt(intRat(14-m), 12))
jdn := floorRat(mulRat(addInt(subRat(y, k), 4800), fracInt(1461, 4)))
jdn = addRat(jdn, floorRat(mulRat(addInt(mulInt(k, 12), m-2), fracInt(367, 12))))
jdn = subRat(jdn, floorRat(mulRat(floorRat(quoInt(addInt(subRat(y, k), 4900), 100)), fracInt(3, 4))))
jdn = addInt(jdn, d-32075)
jdn = addRat(jdn, subRat(quoRat(addRat(intRat(int64(dt.Second()+dt.Minute()*60+dt.Hour()*3600)), fracInt(int64(dt.Nanosecond()), 999999999)), floatRat((24*time.Hour).Seconds())), floatRat(0.5)))
return jdn
}

// GetJDN returns Julian Day Number from time.Time.
func GetJDN(dt time.Time) int64 {
return floorRat(GetJD(dt)).Num().Int64()
}

// GetMJD returns Modified Julian Day from time.Time.
func GetMJD(dt time.Time) *big.Rat {
return subRat(GetJD(dt), floatRat(2400000.5))
}

// GetMJDN returns Modified Julian Day Number from time.Time.
func GetMJDN(dt time.Time) int64 {
return floorRat(GetMJD(dt)).Num().Int64()
}

func intRat(x int64) *big.Rat {
return fracInt(x, 1)
}

func floatRat(x float64) *big.Rat {
return (&big.Rat{}).SetFloat64(x)
}

func fracInt(x, y int64) *big.Rat {
return big.NewRat(x, y)
}

func addInt(x *big.Rat, y int64) *big.Rat {
return addRat(x, intRat(y))
}

// func subInt(x *big.Rat, y int64) *big.Rat {
// return subRat(x, intRat(y))
// }

func mulInt(x *big.Rat, y int64) *big.Rat {
return mulRat(x, intRat(y))
}

func quoInt(x *big.Rat, y int64) *big.Rat {
return quoRat(x, intRat(y))
}

func addRat(x, y *big.Rat) *big.Rat {
return (&big.Rat{}).Add(x, y)
}

func subRat(x, y *big.Rat) *big.Rat {
return (&big.Rat{}).Sub(x, y)
}

func mulRat(x, y *big.Rat) *big.Rat {
return (&big.Rat{}).Mul(x, y)
}

func quoRat(x, y *big.Rat) *big.Rat {
return (&big.Rat{}).Quo(x, y)
}

func floorRat(n *big.Rat) *big.Rat {
return (&big.Rat{}).SetInt((&big.Int{}).Div(n.Num(), n.Denom()))
}

/* Copyright 2022 Spiegel
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
77 changes: 77 additions & 0 deletions jdn/jdn_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package jdn

import (
"math/big"
"testing"
"time"
)

func TestGetJDN(t *testing.T) {
jst := time.FixedZone("JST", int((9 * time.Hour).Seconds())) // Japan standard Time
testCases := []struct {
inp time.Time
outp1 *big.Rat
outp2 int64
outp3 *big.Rat
outp4 int64
}{
{inp: time.Date(2015, time.January, 1, 0, 0, 0, 0, time.UTC), outp1: floatRat(2457023.5), outp2: 2457023, outp3: floatRat(57023.0), outp4: 57023},
{inp: time.Date(2022, time.January, 1, 0, 0, 0, 0, jst), outp1: floatRat(2459580.125), outp2: 2459580, outp3: floatRat(59579.625), outp4: 59579},
}
for _, tc := range testCases {
jd := GetJD(tc.inp)
if jd.Cmp(tc.outp1) != 0 {
t.Errorf("GetJD(%v) is %v, want %v.", tc.inp, jd.FloatString(5), tc.outp1.FloatString(5))
}
jdn := GetJDN(tc.inp)
if jdn != tc.outp2 {
t.Errorf("GetJDN(%v) is %v, want %v.", tc.inp, jdn, tc.outp2)
}
mjd := GetMJD(tc.inp)
if mjd.Cmp(tc.outp3) != 0 {
t.Errorf("GetMJD(%v) is %v, want %v.", tc.inp, mjd.FloatString(5), tc.outp3.FloatString(5))
}
mjdn := GetMJDN(tc.inp)
if mjdn != tc.outp4 {
t.Errorf("GetMJDN(%v) is %v, want %v.", tc.inp, mjdn, tc.outp4)
}
}
}

func TestFloorRat(t *testing.T) {
testCases := []struct {
inp float64
outp float64
}{
{inp: 1.1, outp: 1},
{inp: 1.0, outp: 1},
{inp: 0.9, outp: 0},
{inp: 0.1, outp: 0},
{inp: 0.0, outp: 0},
{inp: -0.1, outp: -1},
{inp: -0.9, outp: -1},
{inp: -1.0, outp: -1},
{inp: -1.1, outp: -2},
}
for _, tc := range testCases {
f := floorRat(floatRat(tc.inp))
if ff, _ := f.Float64(); ff != tc.outp {
t.Errorf("floorRat(%v) is %v, want %v.", tc.inp, f, tc.outp)
}
}
}

/* Copyright 2022 Spiegel
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Loading

0 comments on commit 29b5324

Please sign in to comment.