func RoundDown(t time.Time, d TimeDelta) time.Time {
	td := d.RoundDown(t)
	DebugLogger.Printf("RoundDown( %s, %s ) --> %s", t.Format("2006-01-02 15:04:05 (Mon)"), d.String(),
		td.Format("2006-01-02 15:04:05 (Mon)"))
	return td
}
RoundDown will round tp down to next "full" d.
package chart
import (
	"fmt"
	"time"
)
type TimeDelta interface {
	Seconds() int64                   
	RoundDown(t time.Time) time.Time  
	String() string                   
	Format(t time.Time) string        
	Period() bool                     
}
func cpTime(dest, src time.Time) {
}
type Second struct {
	Num int
}
func (s Second) Seconds() int64 { return int64(s.Num) }
func (s Second) RoundDown(t time.Time) time.Time {
	return t.Add(time.Duration((s.Num*(t.Second()/s.Num))-t.Second()) * time.Second)
}
func (s Second) String() string            { return fmt.Sprintf("%d seconds(s)", s.Num) }
func (s Second) Format(t time.Time) string { return fmt.Sprintf("%02d'%02d\"", t.Minute(), t.Second()) }
func (s Second) Period() bool              { return false }
type Minute struct {
	Num int
}
func (m Minute) Seconds() int64 { return int64(60 * m.Num) }
func (m Minute) RoundDown(t time.Time) time.Time {
	return t.Add(time.Duration(m.Num*(t.Minute()/m.Num)-t.Minute())*time.Minute - time.Duration(t.Second())*time.Second)
}
func (m Minute) String() string            { return fmt.Sprintf("%d minute(s)", m.Num) }
func (m Minute) Format(t time.Time) string { return fmt.Sprintf("%02d'", t.Minute()) }
func (m Minute) Period() bool              { return false }
type Hour struct{ Num int }
func (h Hour) Seconds() int64 { return 60 * 60 * int64(h.Num) }
func (h Hour) RoundDown(t time.Time) time.Time {
	return time.Date(t.Year(), t.Month(), t.Day(), h.Num*(t.Hour()/h.Num), 0, 0, 0, t.Location())
}
func (h Hour) String() string            { return fmt.Sprintf("%d hours(s)", h.Num) }
func (h Hour) Format(t time.Time) string { return fmt.Sprintf("%02d:%02d", t.Hour(), t.Minute()) }
func (h Hour) Period() bool              { return false }
type Day struct{ Num int }
func (d Day) Seconds() int64 { return 60 * 60 * 24 * int64(d.Num) }
func (d Day) RoundDown(t time.Time) time.Time {
	return time.Date(t.Year(), t.Month(), d.Num*((t.Day()-1)/d.Num)+1, 0, 0, 0, 0, t.Location())
}
func (d Day) String() string            { return fmt.Sprintf("%d day(s)", d.Num) }
func (d Day) Format(t time.Time) string { return fmt.Sprintf("%s", t.Format("Mon")) }
func (d Day) Period() bool              { return true }
type Week struct {
	Num int
}
func (w Week) Seconds() int64 { return 60 * 60 * 24 * 7 * int64(w.Num) }
func (w Week) RoundDown(t time.Time) time.Time {
	org := t.Format("Mon 2006-01-02")
	_, week := t.ISOWeek()
	shift := int64(60 * 60 * 24 * (t.Weekday() - time.Monday))
	t = t.Add(-time.Duration(shift) * time.Second)
	t = time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(), 0, t.Location())
	_, week2 := t.ISOWeek()
	for week2 < week {
		DebugLogger.Printf("B  %s", t)
		t = t.Add(time.Second * 60 * 60 * 36)
		t = time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(), 0, t.Location())
		_, week2 = t.ISOWeek()
	}
	for week2 > week {
		DebugLogger.Printf("C  %s", t)
		t = t.Add(-time.Second * 60 * 60 * 36)
		t = time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(), 0, t.Location())
		_, week2 = t.ISOWeek()
	}
	DebugLogger.Printf("Week.Roundown(%s) --> %s", org, t.Format("Mon 2006-01-02"))
	return t
}
func (w Week) String() string { return fmt.Sprintf("%d week(s)", w.Num) }
func (w Week) Format(t time.Time) string {
	_, week := t.ISOWeek()
	return fmt.Sprintf("W %d", week)
}
func (w Week) Period() bool { return true }
type Month struct {
	Num int
}
func (m Month) Seconds() int64 { return 60 * 60 * 24 * 365.25 / 12 * int64(m.Num) }
func (m Month) RoundDown(t time.Time) time.Time {
	return time.Date(t.Year(), time.Month(m.Num*(int(t.Month())-1)/m.Num+1),
		1, 0, 0, 0, 0, t.Location())
}
func (m Month) String() string { return fmt.Sprintf("%d month(s)", m.Num) }
func (m Month) Format(t time.Time) string {
	if m.Num == 3 {  
		return fmt.Sprintf("Q%d %d", (int(t.Month())-1)/3+1, t.Year())
	}
	if m.Num == 6 {  
		return fmt.Sprintf("H%d %d", (int(t.Month())-1)/6+1, t.Year())
	}
	return fmt.Sprintf("%02d.%d", int(t.Month()), t.Year())
}
func (m Month) Period() bool { return true }
type Year struct {
	Num int
}
func (y Year) Seconds() int64 { return 60 * 60 * 24 * 365.25 * int64(y.Num) }
func (y Year) RoundDown(t time.Time) time.Time {
	orig := t.Year()
	rd := y.Num * (orig / y.Num)
	t = time.Date(rd, 1, 1, 0, 0, 0, 0, t.Location())
	DebugLogger.Printf("Year.RoundDown from %d to %d", orig, rd)
	return t
}
func (y Year) String() string { return fmt.Sprintf("%d year(s)", y.Num) }
func (y Year) Format(t time.Time) string {
	if y.Num == 10 {
		y := t.Year() / 10
		d := y % 10
		return fmt.Sprintf("%d0-%d9", y, d)
	} else if y.Num == 100 {
		y := t.Year() / 100
		return fmt.Sprintf("%d cen.", y)
	}
	return fmt.Sprintf("%d", t.Year())
}
func (y Year) Period() bool { return true }
var Delta []TimeDelta = []TimeDelta{
	Second{1}, Second{5}, Second{15},
	Minute{1}, Minute{5}, Minute{15},
	Hour{1}, Hour{6},
	Day{1}, Week{1},
	Month{1}, Month{3}, Month{6},
	Year{1}, Year{10}, Year{100},
}
func RoundUp(t time.Time, d TimeDelta) time.Time {
	shift := d.Seconds()
	shift += shift / 2
	t = d.RoundDown(t)
	t = t.Add(time.Duration(shift) * time.Second)
	t = d.RoundDown(t)
	DebugLogger.Printf("RoundUp( %s, %s ) --> %s ", t.Format("2006-01-02 15:04:05 (Mon)"), d.String(),
		t.Format("2006-01-02 15:04:05 (Mon)"))
	return t
}
func RoundNext(t time.Time, d TimeDelta) time.Time {
	DebugLogger.Printf("RoundNext( %s, %s )", t.Format("2006-01-02 15:04:05 (Mon)"), d.String())
	os := t.Unix()
	lt := d.RoundDown(t)
	shift := d.Seconds()
	shift += shift / 2
	ut := lt.Add(time.Duration(shift) * time.Second)  
	ut = d.RoundDown(ut)
	ld := os - lt.Unix()
	ud := ut.Unix() - os
	if ld < ud {
		return lt
	}
	return ut
}