Skip to content

Commit ca4b23e

Browse files
committed
Close #500: [refined4s-chimney] Add Transformer and PartialTransformer type-class instances for refined4s.types.time types
1 parent 99aa3d6 commit ca4b23e

File tree

4 files changed

+271
-2
lines changed

4 files changed

+271
-2
lines changed

modules/refined4s-chimney/shared/src/main/scala/refined4s/modules/chimney/derivation/types/all.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ package refined4s.modules.chimney.derivation.types
33
/** @author Kevin Lee
44
* @since 2024-08-09
55
*/
6-
trait all extends numeric, strings, network
6+
trait all extends numeric, strings, network, time
77
object all extends all
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package refined4s.modules.chimney.derivation.types
2+
3+
import io.scalaland.chimney
4+
import io.scalaland.chimney.{PartialTransformer, Transformer}
5+
6+
import refined4s.types.time.*
7+
8+
/** @author Kevin Lee
9+
* @since 2025-09-01
10+
*/
11+
trait time {
12+
inline given derivedMonthToIntTransformer: Transformer[Month, Int] = time.derivedMonthToIntTransformer
13+
inline given derivedIntToMonthPartialTransformer: PartialTransformer[Int, Month] = time.derivedIntToMonthPartialTransformer
14+
15+
inline given derivedDayToIntTransformer: Transformer[Day, Int] = time.derivedDayToIntTransformer
16+
inline given derivedIntToDayPartialTransformer: PartialTransformer[Int, Day] = time.derivedIntToDayPartialTransformer
17+
18+
inline given derivedHourToIntTransformer: Transformer[Hour, Int] = time.derivedHourToIntTransformer
19+
inline given derivedIntToHourPartialTransformer: PartialTransformer[Int, Hour] = time.derivedIntToHourPartialTransformer
20+
21+
inline given derivedMinuteToIntTransformer: Transformer[Minute, Int] = time.derivedMinuteToIntTransformer
22+
inline given derivedIntToMinutePartialTransformer: PartialTransformer[Int, Minute] = time.derivedIntToMinutePartialTransformer
23+
24+
inline given derivedSecondToIntTransformer: Transformer[Second, Int] = time.derivedSecondToIntTransformer
25+
inline given derivedIntToSecondPartialTransformer: PartialTransformer[Int, Second] = time.derivedIntToSecondPartialTransformer
26+
27+
inline given derivedMillisToIntTransformer: Transformer[Millis, Int] = time.derivedMillisToIntTransformer
28+
inline given derivedIntToMillisPartialTransformer: PartialTransformer[Int, Millis] = time.derivedIntToMillisPartialTransformer
29+
30+
}
31+
object time {
32+
33+
inline given derivedMonthToIntTransformer: Transformer[Month, Int] with {
34+
override def transform(src: Month): Int = src.value
35+
}
36+
inline given derivedIntToMonthPartialTransformer: PartialTransformer[Int, Month] =
37+
PartialTransformer(value => chimney.partial.Result.fromEitherString(Month.from(value)))
38+
39+
inline given derivedDayToIntTransformer: Transformer[Day, Int] with {
40+
override def transform(src: Day): Int = src.value
41+
}
42+
inline given derivedIntToDayPartialTransformer: PartialTransformer[Int, Day] =
43+
PartialTransformer(value => chimney.partial.Result.fromEitherString(Day.from(value)))
44+
45+
inline given derivedHourToIntTransformer: Transformer[Hour, Int] with {
46+
override def transform(src: Hour): Int = src.value
47+
}
48+
inline given derivedIntToHourPartialTransformer: PartialTransformer[Int, Hour] =
49+
PartialTransformer(value => chimney.partial.Result.fromEitherString(Hour.from(value)))
50+
51+
inline given derivedMinuteToIntTransformer: Transformer[Minute, Int] with {
52+
override def transform(src: Minute): Int = src.value
53+
}
54+
inline given derivedIntToMinutePartialTransformer: PartialTransformer[Int, Minute] =
55+
PartialTransformer(value => chimney.partial.Result.fromEitherString(Minute.from(value)))
56+
57+
inline given derivedSecondToIntTransformer: Transformer[Second, Int] with {
58+
override def transform(src: Second): Int = src.value
59+
}
60+
inline given derivedIntToSecondPartialTransformer: PartialTransformer[Int, Second] =
61+
PartialTransformer(value => chimney.partial.Result.fromEitherString(Second.from(value)))
62+
63+
inline given derivedMillisToIntTransformer: Transformer[Millis, Int] with {
64+
override def transform(src: Millis): Int = src.value
65+
}
66+
inline given derivedIntToMillisPartialTransformer: PartialTransformer[Int, Millis] =
67+
PartialTransformer(value => chimney.partial.Result.fromEitherString(Millis.from(value)))
68+
69+
}

modules/refined4s-chimney/shared/src/test/scala/refined4s/modules/chimney/derivation/types/allSpec.scala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@ object allSpec extends Properties {
1717
object networkSpecWithAll extends networkSpec {
1818
override protected val networkTypeClasses: network = refined4s.modules.chimney.derivation.types.all
1919
}
20+
object timeSpecWithAll extends timeSpec {
21+
override protected val timeTypeClasses: time = refined4s.modules.chimney.derivation.types.all
22+
}
2023

21-
override def tests: List[Test] = numericSpec.allTests ++ stringsSpec.allTests ++ networkSpec.allTests
24+
override def tests: List[Test] =
25+
numericSpec.allTests ++ stringsSpec.allTests ++ networkSpec.allTests ++ timeSpecWithAll.allTests
2226

2327
}
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
package refined4s.modules.chimney.derivation.types
2+
3+
import hedgehog.*
4+
import hedgehog.runner.*
5+
import io.scalaland.chimney
6+
import io.scalaland.chimney.dsl.*
7+
import refined4s.types.TimeGens
8+
import refined4s.types.time.*
9+
10+
/** @author Kevin Lee
11+
* @since 2025-09-01
12+
*/
13+
trait timeSpec {
14+
15+
protected val timeTypeClasses: refined4s.modules.chimney.derivation.types.time
16+
import timeTypeClasses.given
17+
18+
def allTests: List[Test] = List(
19+
// Month
20+
property("test from Month to Int", testFromMonthToInt),
21+
property("test from Int to Month", testToIntToMonth),
22+
// Day
23+
property("test from Day to Int", testFromDayToInt),
24+
property("test from Int to Day", testToIntToDay),
25+
// Hour
26+
property("test from Hour to Int", testFromHourToInt),
27+
property("test from Int to Hour", testToIntToHour),
28+
// Minute
29+
property("test from Minute to Int", testFromMinuteToInt),
30+
property("test from Int to Minute", testToIntToMinute),
31+
// Second
32+
property("test from Second to Int", testFromSecondToInt),
33+
property("test from Int to Second", testToIntToSecond),
34+
// Millis
35+
property("test from Millis to Int", testFromMillisToInt),
36+
property("test from Int to Millis", testToIntToMillis),
37+
)
38+
39+
def testFromMonthToInt: Property =
40+
for {
41+
month <- TimeGens.genMonth.log("month")
42+
} yield {
43+
val input = month
44+
45+
val expected = month.value
46+
val actual = input.into[Int].transform
47+
48+
actual ==== expected
49+
}
50+
51+
def testToIntToMonth: Property =
52+
for {
53+
month <- TimeGens.genMonth.log("month")
54+
} yield {
55+
val input = month.value
56+
57+
val expected = chimney.partial.Result.fromValue(month)
58+
59+
val actual = input.intoPartial[Month].transform
60+
61+
actual ==== expected
62+
}
63+
64+
def testFromDayToInt: Property =
65+
for {
66+
day <- TimeGens.genDay.log("day")
67+
} yield {
68+
val input = day
69+
70+
val expected = day.value
71+
val actual = input.into[Int].transform
72+
73+
actual ==== expected
74+
}
75+
76+
def testToIntToDay: Property =
77+
for {
78+
day <- TimeGens.genDay.log("day")
79+
} yield {
80+
val input = day.value
81+
82+
val expected = chimney.partial.Result.fromValue(day)
83+
84+
val actual = input.intoPartial[Day].transform
85+
86+
actual ==== expected
87+
}
88+
89+
def testFromHourToInt: Property =
90+
for {
91+
hour <- TimeGens.genHour.log("hour")
92+
} yield {
93+
val input = hour
94+
95+
val expected = hour.value
96+
val actual = input.into[Int].transform
97+
98+
actual ==== expected
99+
}
100+
101+
def testToIntToHour: Property =
102+
for {
103+
hour <- TimeGens.genHour.log("hour")
104+
} yield {
105+
val input = hour.value
106+
107+
val expected = chimney.partial.Result.fromValue(hour)
108+
109+
val actual = input.intoPartial[Hour].transform
110+
111+
actual ==== expected
112+
}
113+
114+
def testFromMinuteToInt: Property =
115+
for {
116+
minute <- TimeGens.genMinute.log("minute")
117+
} yield {
118+
val input = minute
119+
120+
val expected = minute.value
121+
val actual = input.into[Int].transform
122+
123+
actual ==== expected
124+
}
125+
126+
def testToIntToMinute: Property =
127+
for {
128+
minute <- TimeGens.genMinute.log("minute")
129+
} yield {
130+
val input = minute.value
131+
132+
val expected = chimney.partial.Result.fromValue(minute)
133+
134+
val actual = input.intoPartial[Minute].transform
135+
136+
actual ==== expected
137+
}
138+
139+
def testFromSecondToInt: Property =
140+
for {
141+
second <- TimeGens.genSecond.log("second")
142+
} yield {
143+
val input = second
144+
145+
val expected = second.value
146+
val actual = input.into[Int].transform
147+
148+
actual ==== expected
149+
}
150+
151+
def testToIntToSecond: Property =
152+
for {
153+
second <- TimeGens.genSecond.log("second")
154+
} yield {
155+
val input = second.value
156+
157+
val expected = chimney.partial.Result.fromValue(second)
158+
159+
val actual = input.intoPartial[Second].transform
160+
161+
actual ==== expected
162+
}
163+
164+
def testFromMillisToInt: Property =
165+
for {
166+
millis <- TimeGens.genMillis.log("millis")
167+
} yield {
168+
val input = millis
169+
170+
val expected = millis.value
171+
val actual = input.into[Int].transform
172+
173+
actual ==== expected
174+
}
175+
176+
def testToIntToMillis: Property =
177+
for {
178+
millis <- TimeGens.genMillis.log("millis")
179+
} yield {
180+
val input = millis.value
181+
182+
val expected = chimney.partial.Result.fromValue(millis)
183+
184+
val actual = input.intoPartial[Millis].transform
185+
186+
actual ==== expected
187+
}
188+
189+
}
190+
object timeSpec extends Properties, timeSpec {
191+
192+
override protected object timeTypeClasses extends refined4s.modules.chimney.derivation.types.time
193+
194+
override def tests: List[Test] = allTests
195+
196+
}

0 commit comments

Comments
 (0)