diff --git a/Sources/Model/Turn.cs b/Sources/Model/Turn.cs
new file mode 100644
index 0000000..f951bb4
--- /dev/null
+++ b/Sources/Model/Turn.cs
@@ -0,0 +1,100 @@
+using System;
+
+namespace Model
+{
+ ///
+ /// a Turn consists of a Player, a DateTime, and a IEnumerable of AbstractDieFace
+ /// Like a turn in some game.
+ ///
+ /// Two turns are equal if they are litterally the same instance in RAM
+ /// (default behaviors Equals() and GetHashCode())
+ ///
+ public class Turn
+ {
+
+ ///
+ /// the date and time, adjusted to UTC
+ ///
+ public readonly DateTime when;
+
+ ///
+ /// the Player who rolled the dice
+ ///
+ public readonly Player player;
+
+ /*
+ public IEnumerable Faces { get; private set; }
+ */
+
+ ///
+ /// this private constructor is to be used only by factories
+ ///
+ /// date and time of the turn
+ /// player who played the turn
+ // TODO add faces
+ private Turn(DateTime when, Player player/*, IEnumerable faces*/)
+ {
+ this.when = when;
+ this.player = player;
+ /*Faces = faces;*/
+ }
+
+ ///
+ /// creates a Turn with a specified time, passed as a parameter.
+ ///
+ /// whatever the DateTimeKind of might be,
+ /// it will become UTC during construction
+ ///
+ /// date and time of the turn
+ /// player who played the turn
+ /// a new Turn object
+ // TODO add faces
+ public static Turn CreateWithSpecifiedTime(DateTime when, Player player/*, IEnumerable faces*/)
+ {
+ // TODO add validation for faces too
+ if (player == null)
+ {
+ throw new ArgumentNullException(nameof(player), "param should not be null");
+ }
+ if (when.Kind != DateTimeKind.Utc)
+ {
+ when = when.ToUniversalTime();
+ }
+
+ return new Turn(when, player/*, faces*/);
+ }
+
+ ///
+ /// creates a Turn with a default time, which is "now" in UTC.
+ ///
+ /// player who played the turn
+ /// a new Turn object
+ // TODO add faces
+ public static Turn CreateWithDefaultTime(Player player/*, IEnumerable faces*/)
+ {
+ return CreateWithSpecifiedTime(DateTime.UtcNow, player/*, faces*/);
+ }
+
+ //TODO add faces
+ ///
+ /// represents a turn in string format
+ ///
+ /// a turn in string format
+ public override string ToString()
+ {
+ //string[] datetime = this.when.ToString("s", System.Globalization.CultureInfo.InvariantCulture).Split("T");
+ //string date = datetime[0];
+ //string time = datetime[1];
+
+ return String.Format("{0} -- {1} rolled {2}",
+ ToStringIsoWithZ(),
+ this.player.ToString(),
+ ", , ...");
+ }
+
+ private string ToStringIsoWithZ()
+ {
+ return this.when.ToString("s", System.Globalization.CultureInfo.InvariantCulture) + "Z";
+ }
+ }
+}
diff --git a/Sources/Tests/Model_UTs/TurnTest.cs b/Sources/Tests/Model_UTs/TurnTest.cs
new file mode 100644
index 0000000..dc85b99
--- /dev/null
+++ b/Sources/Tests/Model_UTs/TurnTest.cs
@@ -0,0 +1,99 @@
+using Model;
+using System;
+using Xunit;
+
+namespace Tests.Model_UTs
+{
+ public class TurnTest
+ {
+ [Fact]
+ public void TestCreateWithSpecifiedTimeNotUTCThenValid()
+ {
+ // Arrange
+ DateTime dateTime = new(year: 2018, month: 06, day: 15, hour: 16, minute: 30, second: 0, kind: DateTimeKind.Local);
+ Player player = new("Alice");
+ Assert.NotEqual(DateTimeKind.Utc, dateTime.Kind);
+
+ // Act
+ Turn turn = Turn.CreateWithSpecifiedTime(dateTime, player);
+
+ // Assert
+ Assert.Equal(DateTimeKind.Utc, turn.when.Kind);
+ Assert.Equal(dateTime.ToUniversalTime(), turn.when);
+ }
+
+ [Fact]
+ public void TestCreateWithSpecifiedTimeUTCThenValid()
+ {
+ // Arrange
+ DateTime dateTime = new(year: 2018, month: 06, day: 15, hour: 16, minute: 30, second: 0, kind: DateTimeKind.Utc);
+ Player player = new("Bobby");
+ Assert.Equal(DateTimeKind.Utc, dateTime.Kind);
+
+ // Act
+ Turn turn = Turn.CreateWithSpecifiedTime(dateTime, player);
+
+ // Assert
+ Assert.Equal(DateTimeKind.Utc, turn.when.Kind);
+ Assert.Equal(dateTime.ToUniversalTime(), turn.when);
+ }
+
+ [Fact]
+ public void TestCreateWithSpecifiedTimeNullPlayerThenException()
+ {
+ // Arrange
+ DateTime dateTime = new(year: 2018, month: 06, day: 15, hour: 16, minute: 30, second: 0, kind: DateTimeKind.Utc);
+
+ // Act
+ void action() => Turn.CreateWithSpecifiedTime(dateTime, null);
+
+ // Assert
+ Assert.Throws(action);
+ }
+
+ [Fact]
+ public void TestCreateWithDefaultTimeThenValid()
+ {
+ // Arrange
+ Player player = new("Chloe");
+
+ // Act
+ Turn turn = Turn.CreateWithDefaultTime(player);
+
+ // Assert
+ Assert.Equal(DateTimeKind.Utc, turn.when.Kind);
+ Assert.Equal(DateTime.Now.ToUniversalTime().Date, turn.when.Date);
+ /*** N.B.: might fail between 11:59:59PM and 00:00:00AM ***/
+ }
+
+ [Fact]
+ public void TestCreateWithDefaultTimeNullPlayerThenException()
+ {
+ // Arrange
+ Player player = new("Devon");
+
+ // Act
+ static void action() => Turn.CreateWithDefaultTime(null);
+
+ // Assert
+ Assert.Throws(action);
+ }
+
+ [Fact]
+ public void TestToStringValidIfAllNormal()
+ {
+ // Arrange
+ DateTime dateTime = new(year: 2018, month: 06, day: 15, hour: 16, minute: 30, second: 0, kind: DateTimeKind.Utc);
+ string name = "Bobby";
+ Player player = new(name);
+ string expected = $"2018-06-15T16:30:00Z -- {name} rolled , , ...";
+ Turn turn = Turn.CreateWithSpecifiedTime(dateTime, player);
+
+ // Act
+ string actual = turn.ToString();
+
+ // Assert
+ Assert.Equal(expected, actual);
+ }
+ }
+}