diff --git a/src/NHibernate.Test/Async/NHSpecificTest/GH3291/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/GH3291/Fixture.cs
new file mode 100644
index 00000000000..3420e7e2199
--- /dev/null
+++ b/src/NHibernate.Test/Async/NHSpecificTest/GH3291/Fixture.cs
@@ -0,0 +1,82 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by AsyncGenerator.
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+
+using System;
+using System.Linq;
+using NUnit.Framework;
+using NHibernate.Linq;
+
+namespace NHibernate.Test.NHSpecificTest.GH3291
+{
+	using System.Threading.Tasks;
+	[TestFixture]
+	public class FixtureAsync : BugTestCase
+	{
+		protected override void OnSetUp()
+		{
+			using (var session = OpenSession())
+			using (var transaction = session.BeginTransaction())
+			{
+				var e1 = new Person { Name = "Bob", DateOfBirth = new DateTime(2009, 12, 23) };
+				session.Save(e1);
+
+				var e2 = new Person { Name = "Sally", DateOfBirth = new DateTime(2018, 9, 30) };
+				session.Save(e2);
+
+				transaction.Commit();
+			}
+		}
+
+		protected override void OnTearDown()
+		{
+			using (var session = OpenSession())
+			using (var transaction = session.BeginTransaction())
+			{
+				session.CreateQuery("delete from System.Object").ExecuteUpdate();
+
+				transaction.Commit();
+			}
+		}
+
+		[Test]
+		public async Task LinqAsync()
+		{
+			using (var session = OpenSession())
+			using (session.BeginTransaction())
+			{
+				DateTime? dateOfSearch = null;
+
+				var result = await ((
+					from person in session.Query<Person>()
+					where dateOfSearch == null || person.DateOfBirth > dateOfSearch
+					select person).ToListAsync());
+
+				Assert.That(result, Has.Count.EqualTo(2));
+			}
+		}
+		
+		[Test]
+		public async Task HqlAsync()
+		{
+			using (var session = OpenSession())
+			using (session.BeginTransaction())
+			{
+				DateTime? dateOfSearch = null;
+
+				var result =
+					await (session.CreateQuery("from Person where :DateOfSearch is null OR DateOfBirth > :DateOfSearch")
+						.SetParameter("DateOfSearch", dateOfSearch, NHibernateUtil.DateTime)
+						.ListAsync<Person>());
+
+				Assert.That(result, Has.Count.EqualTo(2));
+			}
+		}
+	}
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/GH3291/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/GH3291/Fixture.cs
new file mode 100644
index 00000000000..1cf8f418f67
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH3291/Fixture.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Linq;
+using NUnit.Framework;
+
+namespace NHibernate.Test.NHSpecificTest.GH3291
+{
+	[TestFixture]
+	public class Fixture : BugTestCase
+	{
+		protected override void OnSetUp()
+		{
+			using (var session = OpenSession())
+			using (var transaction = session.BeginTransaction())
+			{
+				var e1 = new Person { Name = "Bob", DateOfBirth = new DateTime(2009, 12, 23) };
+				session.Save(e1);
+
+				var e2 = new Person { Name = "Sally", DateOfBirth = new DateTime(2018, 9, 30) };
+				session.Save(e2);
+
+				transaction.Commit();
+			}
+		}
+
+		protected override void OnTearDown()
+		{
+			using (var session = OpenSession())
+			using (var transaction = session.BeginTransaction())
+			{
+				session.CreateQuery("delete from System.Object").ExecuteUpdate();
+
+				transaction.Commit();
+			}
+		}
+
+		[Test]
+		public void Linq()
+		{
+			using (var session = OpenSession())
+			using (session.BeginTransaction())
+			{
+				DateTime? dateOfSearch = null;
+
+				var result = (
+					from person in session.Query<Person>()
+					where dateOfSearch == null || person.DateOfBirth > dateOfSearch
+					select person).ToList();
+
+				Assert.That(result, Has.Count.EqualTo(2));
+			}
+		}
+		
+		[Test]
+		public void Hql()
+		{
+			using (var session = OpenSession())
+			using (session.BeginTransaction())
+			{
+				DateTime? dateOfSearch = null;
+
+				var result =
+					session.CreateQuery("from Person where :DateOfSearch is null OR DateOfBirth > :DateOfSearch")
+						.SetParameter("DateOfSearch", dateOfSearch, NHibernateUtil.DateTime)
+						.List<Person>();
+
+				Assert.That(result, Has.Count.EqualTo(2));
+			}
+		}
+	}
+}
diff --git a/src/NHibernate.Test/NHSpecificTest/GH3291/Mappings.hbm.xml b/src/NHibernate.Test/NHSpecificTest/GH3291/Mappings.hbm.xml
new file mode 100644
index 00000000000..1088c98b593
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH3291/Mappings.hbm.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernate.Test"
+                   namespace="NHibernate.Test.NHSpecificTest.GH3291">
+
+  <class name="Person">
+    <id name="Id" generator="guid.comb"/>
+    <property name="Name"/>
+    <property name="DateOfBirth" />
+  </class>
+
+</hibernate-mapping>
diff --git a/src/NHibernate.Test/NHSpecificTest/GH3291/Person.cs b/src/NHibernate.Test/NHSpecificTest/GH3291/Person.cs
new file mode 100644
index 00000000000..d80efc2e094
--- /dev/null
+++ b/src/NHibernate.Test/NHSpecificTest/GH3291/Person.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace NHibernate.Test.NHSpecificTest.GH3291
+{
+	class Person
+	{
+		public virtual Guid Id { get; set; }
+		public virtual string Name { get; set; }
+		public virtual DateTime? DateOfBirth { get; set; }
+	}
+}
diff --git a/src/NHibernate.TestDatabaseSetup/TestDatabaseSetup.cs b/src/NHibernate.TestDatabaseSetup/TestDatabaseSetup.cs
index 5dd5fc8fe22..deea09fb3a5 100644
--- a/src/NHibernate.TestDatabaseSetup/TestDatabaseSetup.cs
+++ b/src/NHibernate.TestDatabaseSetup/TestDatabaseSetup.cs
@@ -182,11 +182,7 @@ private static void SetupNpgsql(Cfg.Configuration cfg)
 
 				using (var cmd = conn.CreateCommand())
 				{
-					cmd.CommandText =
-						@"CREATE OR REPLACE FUNCTION uuid_generate_v4()
-						RETURNS uuid
-						AS '$libdir/uuid-ossp', 'uuid_generate_v4'
-						VOLATILE STRICT LANGUAGE C;";
+					cmd.CommandText = "CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\";";
 
 					cmd.ExecuteNonQuery();
 				}
diff --git a/src/NHibernate/Driver/NpgsqlDriver.cs b/src/NHibernate/Driver/NpgsqlDriver.cs
index c638e256221..9a4a4b06771 100644
--- a/src/NHibernate/Driver/NpgsqlDriver.cs
+++ b/src/NHibernate/Driver/NpgsqlDriver.cs
@@ -1,3 +1,4 @@
+using System;
 using System.Data;
 using System.Data.Common;
 using NHibernate.AdoNet;
@@ -74,14 +75,37 @@ protected override void InitializeParameter(DbParameter dbParam, string name, Sq
 				// Since the .NET currency type has 4 decimal places, we use a decimal type in PostgreSQL instead of its native 2 decimal currency type.
 				dbParam.DbType = DbType.Decimal;
 			}
-			else if (DriverVersionMajor < 6 || sqlType.DbType != DbType.DateTime)
+			else
 			{
 				dbParam.DbType = sqlType.DbType;
 			}
-			else
+		}
+
+		public override void AdjustCommand(DbCommand command)
+		{
+			if (DriverVersionMajor >= 6)
 			{
-				// Let Npgsql 6 driver to decide parameter type 
+				for (var i = 0; i < command.Parameters.Count; i++)
+				{
+					var parameter = command.Parameters[i];
+					if (parameter.DbType == DbType.DateTime &&
+					    parameter.Value is DateTime dateTime &&
+					    dateTime.Kind != DateTimeKind.Utc)
+					{
+						// There are breaking changes in Npgsql 6 as following:
+						// UTC DateTime is now strictly mapped to timestamptz,
+						// while Local/Unspecified DateTime is now strictly mapped to timestamp.
+						//
+						// DbType.DateTime now maps to timestamptz, not timestamp.
+						// DbType.DateTime2 continues to map to timestamp
+						//
+						// See more details here: https://www.npgsql.org/doc/release-notes/6.0.html#detailed-notes
+						parameter.DbType = DbType.DateTime2;
+					}
+				}
 			}
+
+			base.AdjustCommand(command);
 		}
 
 		// Prior to v3, Npgsql was expecting DateTime for time.