Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/static/llms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ observable.Subscribe(ro.OnNext(func(s string) {
- **bytes** - Byte slice manipulation operators
- **strings** - String manipulation operators (Capitalize, CamelCase, SnakeCase, etc.)
- **sort** - Sorting operators
- **time** - Time manipulation

### Encoding & Serialization
- **encoding/json** - JSON marshaling and unmarshaling
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ require (
golang.org/x/text v0.22.0 // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
)
1 change: 1 addition & 0 deletions go.work
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ use (
./plugins/strings
./plugins/template
./plugins/testify
./plugins/time
./plugins/websocket/client
)

Expand Down
170 changes: 170 additions & 0 deletions plugins/time/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
# Time Plugin

The time plugin provides operators for manipulating dates/time object in reactive streams.

## Installation

```bash
go get github.com/samber/ro/plugins/time
```

## Operators

### Add

Add a duration to a date

```go
import (
"github.com/samber/ro"
rotime "github.com/samber/ro/plugins/time"
)

observable := ro.Pipe1(
ro.Just(
time.Date(2026, time.January, 7, 14, 30, 0, 0, time.UTC),
time.Date(0, time.January, 1, 23, 59, 59, 0, time.UTC),
),
rotime.Add(2 * time.Hour),
)

// Output:
// Next: time.Date(2026, time.January, 7, 16, 30, 0, 0, time.UTC)
// Next: time.Date(0, time.January, 2, 1, 59, 59, 0, time.UTC)
// Completed
```

### AddDate

Add a duration defined by years, months, days to a date.

```go
import (
"github.com/samber/ro"
rotime "github.com/samber/ro/plugins/time"
)

observable := ro.Pipe1(
ro.Just(
time.Date(2026, time.January, 7, 14, 30, 0, 0, time.UTC),
),
rotime.AddDate(0, 1, 0),
)

// Output:
// Next: time.Date(2026, time.February, 7, 14, 30, 0, 0, time.UTC)
// Completed
```

### Format

Transform an observable time.Time into a string, formatted according to the provided layout.

```go
import (
"github.com/samber/ro"
rotime "github.com/samber/ro/plugins/time"
)

observable := ro.Pipe1(
ro.Just(
time.Date(2026, time.January, 7, 14, 30, 0, 0, time.UTC),
),
rotime.Format("2006-01-02 15:04:05"),
)

// Output:
// Next: "2026-01-07 14:30:00"
// Completed
```

### In

Transform an observable time.Time into a string, formatted according to the provided layout.

```go
import (
"github.com/samber/ro"
rotime "github.com/samber/ro/plugins/time"
)

observable := ro.Pipe1(
ro.Just(
time.Date(2026, time.January, 7, 14, 30, 0, 0, time.UTC),
),
rotime.In(time.LoadLocation("Europe/Paris")),
)

// Output:
// Next: time.Date(2026, time.January, 7, 16, 30, 0, 0, time.CET),
// Completed
```

### Parse

Transform an observable string into an observable of time.Time.

```go
import (
"github.com/samber/ro"
rotime "github.com/samber/ro/plugins/time"
)

observable := ro.Pipe1(
ro.Just(
"2026-01-07 14:30:00",
),
rotime.Parse("2006-01-02 15:04:05"),
)

// Output:
// Next: time.Date(2026, time.January, 7, 14, 30, 0, 0, time.UTC)
// Completed
```

### ParseInLocation

Transform an observable string into an observable of time.Time, using location.

```go
import (
"github.com/samber/ro"
rotime "github.com/samber/ro/plugins/time"
)

observable := ro.Pipe1(
ro.Just(
"2026-01-07 14:30:00",
),
rotime.ParseInLocation("2006-01-02 15:04:05", time.UTC),
)

// Output:
// Next: time.Date(2026, time.January, 7, 14, 30, 0, 0, time.UTC)
// Completed
```

### StartOfDay

Truncates the time to the beginning of its day in the local time zone

```go
import (
"github.com/samber/ro"
rotime "github.com/samber/ro/plugins/time"
)

observable := ro.Pipe1(
ro.Just(
time.Date(2026, time.January, 7, 14, 30, 0, 0, time.UTC),
),
rotime.StartOfDay(),
)

// Output:
// Next: time.Date(2026, time.January, 7, 0, 0, 0, 0, time.UTC)
// Completed
```

## Performance Considerations
- The time plugin uses Go's standard `time` package for operations
17 changes: 17 additions & 0 deletions plugins/time/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module github.com/samber/ro/plugins/time

go 1.18

require (
github.com/samber/ro v0.2.0
github.com/stretchr/testify v1.11.1
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/samber/lo v1.52.0 // indirect
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect
golang.org/x/text v0.22.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
20 changes: 20 additions & 0 deletions plugins/time/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/samber/lo v1.52.0 h1:Rvi+3BFHES3A8meP33VPAxiBZX/Aws5RxrschYGjomw=
github.com/samber/lo v1.52.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0=
github.com/samber/ro v0.2.0 h1:pwhLFGZprz+3KyE3JIUnv8GGF/ADpIpvFUEDxuzfGbY=
github.com/samber/ro v0.2.0/go.mod h1:eInj5R1BbXfGoT1ef0HIO5Qie0wlPkkyL0koOaEmfNM=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 h1:3MTrJm4PyNL9NBqvYDSj3DHl46qQakyfqfWo4jgfaEM=
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
57 changes: 57 additions & 0 deletions plugins/time/operator_add.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright 2025 samber.
//
// 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
//
// https://github.com/samber/ro/blob/main/licenses/LICENSE.apache.md
//
// 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.

package rotime

import (
"time"

"github.com/samber/ro"
)

// Add returns an operator that adds a fixed duration to each time value.
//
// Example:
//
// obs := ro.Pipe1(
// ro.Just(time.Now()),
// rotime.Add(2*time.Hour),
// )
//
// The observable then emits: time.Now().Add(2 * time.Hour).
func Add(d time.Duration) func(destination ro.Observable[time.Time]) ro.Observable[time.Time] {
return ro.Map(
func(value time.Time) time.Time {
return value.Add(d)
},
)
}

// AddDate returns an operator that adds a date offset (years, months, days) to each time value.
//
// Example:
//
// obs := ro.Pipe1(
// ro.Just(time.Date(2026, time.January, 7, 14, 30, 0, 0, time.UTC)),
// rotime.AddDate(0, 1, 0),
// )
//
// The observable then emits: time.Date(2026, time.February, 7, 14, 30, 0, 0, time.UTC).
func AddDate(years int, months int, days int) func(destination ro.Observable[time.Time]) ro.Observable[time.Time] {
return ro.Map(
func(value time.Time) time.Time {
return value.AddDate(years, months, days)
},
)
}
Loading
Loading