Skip to content

Commit

Permalink
add timestamp converter
Browse files Browse the repository at this point in the history
  • Loading branch information
sivukhin committed Feb 24, 2024
1 parent 529f8aa commit e31c78f
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 6 deletions.
32 changes: 27 additions & 5 deletions godjotblog/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,13 @@ type Article struct {
Meta Meta
Link, Title, Content, Desc, Date string
Hide bool
Tool bool
}

type Articles struct {
Meta Meta
Articles []Article
Tools []Article
}

var (
Expand Down Expand Up @@ -82,6 +84,7 @@ func build(dir string, meta Meta) {
log.Printf("build godjotblog: start at dir '%v'", dir)
startTime := time.Now()
articles := make([]Article, 0)
tools := make([]Article, 0)
err := filepath.Walk(dir, func(path string, info fs.FileInfo, err error) error {
if info == nil || info.IsDir() {
return nil
Expand All @@ -94,14 +97,16 @@ func build(dir string, meta Meta) {
return err
}
ast := djot_parser.BuildDjotAst(djot)
var date, title, desc, hide string
var date, title, desc, hide, tool string
for _, node := range ast {
node.Traverse(func(node djot_parser.TreeNode[djot_parser.DjotNode]) {
if node.Type != djot_parser.HeadingNode {
return
}
if dateAttr, ok := node.Attributes.TryGet("date"); ok && date == "" {
if title == "" {
title = string(node.FullText())
}
if dateAttr, ok := node.Attributes.TryGet("date"); ok && date == "" {
date = dateAttr
}
if descAttr, ok := node.Attributes.TryGet("desc"); ok && desc == "" {
Expand All @@ -110,6 +115,9 @@ func build(dir string, meta Meta) {
if hideAttr, ok := node.Attributes.TryGet("hide"); ok && hide == "" {
hide = hideAttr
}
if toolAttr, ok := node.Attributes.TryGet("tool"); ok && tool == "" {
tool = toolAttr
}
})
}
htmlPath := strings.TrimSuffix(path, ".dj") + ".html"
Expand Down Expand Up @@ -182,22 +190,36 @@ func build(dir string, meta Meta) {
},
},
).ConvertDjotToHtml(&html_writer.HtmlWriter{Indentation: 4, TabSize: 2}, ast...)
article := Article{Link: link, Meta: meta, Title: title, Desc: desc, Date: date, Content: content, Hide: hide == "true"}
articles = append(articles, article)
article := Article{
Link: link,
Meta: meta,
Title: title,
Desc: desc,
Date: date,
Content: content,
Hide: hide == "true",
Tool: tool == "true",
}
if article.Tool {
tools = append(tools, article)
} else {
articles = append(articles, article)
}
return articleTemplate.Execute(f, article)
})
if err != nil {
panic(err)
}
sort.Slice(articles, func(i, j int) bool { return articles[i].Date > articles[j].Date })
sort.Slice(tools, func(i, j int) bool { return articles[i].Title < articles[j].Title })

renderFile := func(p string, tmpl *template.Template) {
f, err := os.OpenFile(p, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0660)
if err != nil {
panic(err)
}
defer f.Close()
err = tmpl.Execute(f, Articles{Meta: meta, Articles: articles})
err = tmpl.Execute(f, Articles{Meta: meta, Articles: articles, Tools: tools})
if err != nil {
panic(err)
}
Expand Down
8 changes: 8 additions & 0 deletions godjotblog/templates/index_all.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ <h2><a href="about.html">about</a></h2>
{{ end }}
</ul>
</div>
<h4>Tools</h4>
<div class="list">
<ul>
{{ range .Tools }}
<li><a href="{{ .Link }}">{{ .Title }}</a></li>
{{ end }}
</ul>
</div>
<hr/>
<div class="footer">
<p><a href="https://github.com/sivukhin/sivukhin.github.io">github link</a> (made with <a href="https://github.com/sivukhin/godjot">godjot</a> and <a href="https://github.com/sivukhin/gopeg">gopeg</a>)</p>
Expand Down
8 changes: 8 additions & 0 deletions index_all.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ <h2><a href="about.html">about</a></h2>

</ul>
</div>
<h4>Tools</h4>
<div class="list">
<ul>

<li><a href="tools/timestamp_converter.html">Timestamp converter</a></li>

</ul>
</div>
<hr/>
<div class="footer">
<p><a href="https://github.com/sivukhin/sivukhin.github.io">github link</a> (made with <a href="https://github.com/sivukhin/godjot">godjot</a> and <a href="https://github.com/sivukhin/gopeg">gopeg</a>)</p>
Expand Down
2 changes: 1 addition & 1 deletion random-bits-compression-is-hard.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ <h2><a href="/">naming is hard</a></h2>
<pre class="language-python"><code><span class="keyword">import</span> <span class="identifier">random</span></code>
<code><span class="keyword">def</span> <span class="function">random_bytes</span>(<span class="identifier">count</span>, <span class="identifier">p</span>):</code>
<code> <span class="identifier">bit_string</span> = <span class="string">''</span>.<span class="function">join</span>([<span class="string">'1'</span> <span class="keyword">if</span> <span class="identifier">random</span>.<span class="function">random</span>() < <span class="identifier">p</span> <span class="keyword">else</span> <span class="string">'0'</span> <span class="keyword">for</span> _ <span class="keyword">in</span> <span class="function">range</span>(<span class="number">8</span> * <span class="identifier">count</span>)])</code>
<code> <span class="keyword">return</span> <span class="function">bytes</span>([<span class="keyword">in</span><span class="function">t</span>(<span class="identifier">bit_string</span>[<span class="number">8</span>*<span class="identifier">b</span>:<span class="number">8</span>*(<span class="identifier">b</span><span class="number">+1</span>)], <span class="number">2</span>) <span class="keyword">for</span> <span class="identifier">b</span> <span class="keyword">in</span> <span class="function">range</span>(<span class="number">0</span>, <span class="identifier">count</span>)])</code>
<code> <span class="keyword">return</span> <span class="function">bytes</span>([<span class="function">int</span>(<span class="identifier">bit_string</span>[<span class="number">8</span>*<span class="identifier">b</span>:<span class="number">8</span>*(<span class="identifier">b</span><span class="number">+1</span>)], <span class="number">2</span>) <span class="keyword">for</span> <span class="identifier">b</span> <span class="keyword">in</span> <span class="function">range</span>(<span class="number">0</span>, <span class="identifier">count</span>)])</code>
</pre>
<p>In theory, for such simple generation procedure <code>8*count * (p*log(1/p) + q*log(1/q)), q=1-p</code> bits is necessary and enough to encode byte sequence.</p>
<p>Let&rsquo;s look how well <code>zstd</code> can cope with this data:</p>
Expand Down
45 changes: 45 additions & 0 deletions tools/timestamp_converter.dj
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{tool="true"}
# Timestamp converter

`<input id="parse"/> <button onclick="parse()">parse</button> <span id="parsed"/>`{=html}

``` =html
<script>
var timestamp = Date.now()
var searchParams = new URLSearchParams(window.location.search);
if (searchParams.get("q") != null) {
document.getElementById("parse").value = searchParams.get("q");
} else {
document.getElementById("parse").value = Date.now();
}
parse();

function parse() {
var parsed = document.getElementById("parsed");
var text = document.getElementById("parse").value;
var timestamp = parseInt(text);
var date = null, unit = null;
if (!isNaN(timestamp) && timestamp >= 0) {
if (timestamp < 31_536_000_000) { // we have seconds here (31536000000 ~ 1000 years since 1970)
date = new Date(timestamp * 1000);
unit = "seconds";
} else if (timestamp < 31_536_000_000_000) { // we have milliseconds here
date = new Date(timestamp);
unit = "milliseconds";
} else if (timestamp < 31_536_000_000_000_000) { // we have nanoseconds here
date = new Date(timestamp / 1000);
unit = "nanoseconds";
}
}
if (date == null) {
parsed.innerText = "invalid timestamp '" + text + "'";
} else {
parsed.innerText = date.toUTCString() + " (units: " + unit + ")";
var searchParams = new URLSearchParams(window.location.search);
searchParams.set("q", timestamp);
var newRelativePathQuery = window.location.pathname + '?' + searchParams.toString();
history.pushState(null, '', newRelativePathQuery);
}
}
</script>
```
67 changes: 67 additions & 0 deletions tools/timestamp_converter.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="author" content="Nikita Sivukhin"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Timestamp converter</title>
<link rel="stylesheet" href="/static/style.css">
</head>
<body>
<div class="page">
<div class="meta">
<header>
<h2><a href="/">naming is hard</a></h2>
</header>
</div>
<div class="article">
<section id="Timestamp-converter">
<a class="heading-anchor" href="#Timestamp-converter"><h1 tool="true">Timestamp converter</h1>
</a><p><input id="parse"/> <button onclick="parse()">parse</button> <span id="parsed"/></p>
<script>
var timestamp = Date.now()
var searchParams = new URLSearchParams(window.location.search);
if (searchParams.get("q") != null) {
document.getElementById("parse").value = searchParams.get("q");
} else {
document.getElementById("parse").value = Date.now();
}
parse();

function parse() {
var parsed = document.getElementById("parsed");
var text = document.getElementById("parse").value;
var timestamp = parseInt(text);
var date = null, unit = null;
if (!isNaN(timestamp) && timestamp >= 0) {
if (timestamp < 31_536_000_000) { // we have seconds here (31536000000 ~ 1000 years since 1970)
date = new Date(timestamp * 1000);
unit = "seconds";
} else if (timestamp < 31_536_000_000_000) { // we have milliseconds here
date = new Date(timestamp);
unit = "milliseconds";
} else if (timestamp < 31_536_000_000_000_000) { // we have nanoseconds here
date = new Date(timestamp / 1000);
unit = "nanoseconds";
}
}
if (date == null) {
parsed.innerText = "invalid timestamp '" + text + "'";
} else {
parsed.innerText = date.toUTCString() + " (units: " + unit + ")";
var searchParams = new URLSearchParams(window.location.search);
searchParams.set("q", timestamp);
var newRelativePathQuery = window.location.pathname + '?' + searchParams.toString();
history.pushState(null, '', newRelativePathQuery);
}
}
</script>
</section>
</div>
<hr/>
<div class="footer">
<p><a href="https://github.com/sivukhin/sivukhin.github.io">github link</a> (made with <a href="https://github.com/sivukhin/godjot">godjot</a> and <a href="https://github.com/sivukhin/gopeg">gopeg</a>)</p>
</div>
</div>
</body>
</html>

0 comments on commit e31c78f

Please sign in to comment.