package taskwarrior import ( "bytes" "encoding/json" "fmt" "os" "os/exec" "strings" "time" ) /// A task with an Id of 0 is either `completed` or `deleted` which is also /// mentioned in the Status field type Task struct { Id uint `json:"id,omitempty"` Git_number float32 `json:"git_number,omitempty"` // uda Git_type string `json:"git_type,omitempty"` // uda Project string `json:"project,omitempty"` Tags []string `json:"tags,omitempty"` Description string `json:"description,omitempty"` Annotations []Annotation `json:"annotations,omitempty"` Git_comment_ids string `json:"git_comment_ids,omitempty"` // uda Status string `json:"status,omitempty"` Depends []string `json:"depends,omitempty"` Due string `json:"due,omitempty"` Entry string `json:"entry,omitempty"` Modified string `json:"modified,omitempty"` End string `json:"end,omitempty"` Last_gitw_update string `json:"last_gitw_update,omitempty"` // uda Uuid string `json:"uuid,omitempty"` Urgency float32 `json:"urgency,omitempty"` } type Annotation struct { Id int `json:"-"` Description string `json:"description,omitempty"` Entry string `json:"entry,omitempty"` } func (task *Task) AppendComment(comment_id int, description string, time time.Time) { annotation := Annotation{ Id: comment_id, Description: description, Entry: GoTimeToTaskTime(time), } var comment_ids []string comment_ids = nil if len(task.Git_comment_ids) > 0 { comment_ids = strings.Split(task.Git_comment_ids, ",") } comment_ids = append(comment_ids, fmt.Sprintf("%d", comment_id)) task.Git_comment_ids = strings.Join(comment_ids, ",") task.Annotations = append(task.Annotations, annotation) } func NewTask(description string, project string, git_number uint, git_type Type, tags ...string) Task { return Task{ Project: project, Description: description, Git_number: float32(git_number), Git_type: string(git_type), Last_gitw_update: GoTimeToTaskTime(time.Now()), Tags: tags, } } func TaskTimeToGoTime(t string) time.Time { splits := strings.Split(t, "T") if len(t) == 0 { return time.UnixMicro(0) } if len(splits) != 2 { fmt.Fprintf(os.Stderr, "Expected exactly 2 splits") os.Exit(-1) } date := splits[0] first := date[0:4] second := date[4:6] third := date[6:] date = strings.Join([]string{first, second, third}, "-") timestamp := splits[1] first = timestamp[0:2] second = timestamp[2:4] third = timestamp[4 : len(timestamp)-1] timestamp = strings.Join([]string{first, second, third}, ":") // TODO: identify current timezone and use correct format string (works for Europe/Berlin) // FIXME: the +02:00 no longer is correct due to the time shift in CET time! it is now only +01:00 // I'll have to use a better solution, to automatically derive the correct time value := fmt.Sprintf("%sT%s+01:00", date, timestamp) result, err := time.Parse(time.RFC3339, value) if err != nil { fmt.Fprint(os.Stderr, err) os.Exit(-1) } return result.In(time.Local) } func GoTimeToTaskTime(t time.Time) string { result := t.In(time.UTC).Format(time.RFC3339) result = strings.Replace(result, "-", "", 2) result = strings.Replace(result, ":", "", 2) return result } func GetTasks(filter Filter) ([]Task, error) { filter.filter = append(filter.filter, "export") cmd := exec.Command("task", filter.filter...) out, err := cmd.Output() if err != nil { return nil, err } var tasks []Task decoder := json.NewDecoder(bytes.NewBuffer(out)) if err = decoder.Decode(&tasks); err != nil { return nil, err } return tasks, nil } func UpdateTasks(tasks []Task) error { cmd := exec.Command("task", "import") value, err := json.Marshal(tasks) if err != nil { return err } var buffer bytes.Buffer _, err = buffer.Write(value) if err != nil { return err } cmd.Stdin = &buffer return cmd.Run() }