find ZonedDateTime is today, yesterday or else - kotlin

I have a list of ZonedDateTime objects (Eg. 2023-01-01T20:40:01.001+05:30[Asia/Kolkata])
I need to write a method to get the below results.
if ZonedDateTime is today -> return "Today"
if ZonedDateTime is yesterday -> return "Yesterday"
else -> return ZonedDateTime in "yyyy-MM-dd" format -> (Eg. DateTimeFormatter.ofPattern("yyyy-MM-dd").format(zonedDateTime))
How can I calculate if ZonedDateTime is today, tomorrow or else? "Today" as seen in the same timezone as ZonedDateTime object.

You don't actually need to work with ZonedDateTimes for the most part. Just find out what day today is in the desired ZoneId, and then work with LocalDates from that point onwards.
Check if toLocalDate() is equal to today, or if it is equal to today minus one day.
public static String getRelativeDateString(ZonedDateTime zdt) {
var today = LocalDate.now(zdt.getZone());
var ld = zdt.toLocalDate();
if (ld.equals(today)) {
return "Today";
} else if (ld.equals(today.minusDays(1))) {
return "Yesterday";
} else {
return ld.format(DateTimeFormatter.ISO_LOCAL_DATE /* or another formatter */);
}
}

Related

How to get the first value from a list without exceptions in Kotlin?

I have a date value in format "2021-07-14T13:00:00.000+0300" (or similar). I want to convert it to Date. In this case I have to traverse a loop of different formats and check if they fail.
import java.text.*
import java.util.*
val formats = listOf(
"yyyy-MM-dd'T'HH:mm:ss.SSSZ",
"dd.MM.yyyy, EEEE, HH:mm" // And many others.
)
val date = "2021-07-14T13:00:00.000+0300"
val locale = Locale.getDefault()
for (format in formats) {
try {
return SimpleDateFormat(format, locale).parse(date)
} catch (e: ParseException) {
}
}
// If nothing found, return current date.
return Date()
How to convert this for-loop to something like map? So that we can get the first value without exception?
val result = formats.map { ... }
Another option, while still using firstNotNullOfOrNull(), is to use parse() with a ParsePosition object whose properties you can safely ignore when combined with setLenient(false)*.
The advantage of the parse​(String, ParsePosition) version over parse​(String) is that it returns null when it can't parse the date, instead of throwing an error, so the try-catch overhead per iteration can be avoided.
Along with that, since you're defaulting to the current date if all formats fail, you can avoid the nullable Date type result with an Elvis op at the very end.
val result: Date = formats.firstNotNullOfOrNull { format ->
with (SimpleDateFormat(format, locale)) {
setLenient(false) // may not be required, see below
parse(date, ParsePosition(0)) // is null or Date
}
} ?: Date()
Btw, setLenient(false) may not be required because on v15, there's no leniency for SimpleDateFormat.parse() in the docs...but it does behave leniently. Setting it to true above or leaving it out, and parsing a date of "2021-07-14T53:00:00.000+0300" (note the '53') produced Fri Jul 16 02:00:00 UTC 2021. With no leniency, it produces null. The leniency is mentioned on the abstract base class DateFormat.parse(String, ParsePosition) but not for SimpleDateFormat.parse(String, ParsePosition).
So if you're expecting non-pattern-matching dates rather than invalid-but-pattern-matching dates, the above loop could be reduced to:
val result: Date = formats.firstNotNullOfOrNull { format ->
SimpleDateFormat(format, locale).parse(date, ParsePosition(0))
} ?: Date()
Use firstNotNullOfOrNull().
val result: Date? = formats.firstNotNullOfOrNull { format ->
try {
SimpleDateFormat(format, locale).parse(date)
} catch (e: ParseException) {
null
}
}

How to test current date condition in behat?

I have feature that is based on current date, and the question is if it is good solution to write if condition in scenario. Simple example: if tested date is equal to current then other field is equal to 0 else equal 10. Meybe there are libraries to mock current date time in symfony 4.
You could write a step like:
Then I should see sysdate with format "Y-m-d" in the "example" field
Then for your context:
public function iShouldSeeSysdateWithFormatInTheField(string $format, string $key)
{
$field = $this->getSession()->getPage()->findField($key);
$value = (new DateTime())->format($format);
if (is_null($field->getValue())) {
assertEmpty($value);
}
if($value != $field->getValue()) {
throw new Exception('date does not match');
}
}

Search between Specific Times

I have a date field and 2 time fields(Start Time and End Time). I have to get Data from the date and entered in that date field and between Start and end times.
I am using Linq query.
result = result.Where(x => x.CreatedDate.ToLocalTime() > search.StartTime &&
x.CreatedDate.ToLocalTime() < search.EndTime);
I am using this but I am getting the following error.
LINQ to Entities does not recognize the method 'System.DateTime ToLocalTime()' method, and this method cannot be translated into a store expression
Please Help.
You can't use ToLocalTime() for Linq to Entities. Because it can't be translated to SQL. There is no equivalent to apply it.
So, why don't you convert your startTime and endTime by considering required time zone which is stored in the database. Opposite conversion should be like that;
//I use utc time to provide example.
//Convert your dates with required timezones which is stored in the database
var startTime = search.StartTime.ToUtcDateTime();
var endTime = search.EndTime.ToUtcDateTime();
result = result.Where(x => x.CreatedDate > startTime &&
x.CreatedDate < endTime);
As Panagiotis Kanavos pointed out there may be no equivalent argument. When you do have the correct type though you are essentially doing a conversion of one DateTime to another. Both the predicate values and the set should have their values preferably stored in the same TimeZone. Here is a simple console example to show what I mean.
public class TestData
{
public DateTime Dt { get; set; }
public TestData(DateTime dt)
{
Dt = dt;
}
public override string ToString() => Dt.ToString();
}
static void Main(string[] args)
{
var dt = new DateTime(2018, 1, 11);
var s = dt;
var e = dt.AddHours(3);
var dts = new List<TestData>();
for (int i = 0; i < 10; i++)
{
dts.Add(new TestData(dt.AddHours(i)));
}
Console.WriteLine("Dates as are");
dts.ForEach(Console.WriteLine);
Console.WriteLine(Environment.NewLine);
Console.WriteLine("Dates to local time are");
dts.ForEach(x => Console.WriteLine(x.Dt.ToLocalTime()));
Console.WriteLine(Environment.NewLine);
Console.WriteLine("searches are");
Console.WriteLine(s);
Console.WriteLine(e);
Console.WriteLine(Environment.NewLine);
Console.WriteLine("searches to local time are");
Console.WriteLine(s.ToLocalTime());
Console.WriteLine(e.ToLocalTime());
Console.WriteLine(Environment.NewLine);
Console.WriteLine("Weird results as one set is cast to local and other is not. Plus the cast is now performed on presentation");
dts.Where(x => x.Dt.ToLocalTime() >= s && x.Dt.ToLocalTime() <= e).ToList().ForEach(Console.WriteLine);
Console.WriteLine(Environment.NewLine);
Console.WriteLine("expected results as both are uniform");
dts.Where(x => x.Dt >= s && x.Dt <= e).ToList().ForEach(Console.WriteLine);
Console.ReadLine();
}
Since different posters on SO are in different timezone the second result set will vary. But essentially I am in PST in the US so I see times for the second set eight hours prior to my first. You generally in .NET perform operations of storage to be UTC if your application is going to be worldwide or even country wide. Then you just deal with DateTimes and would only do a conversion on the client end for presentation to a potential end user. But most of the time not in the logic for predicates.

How to prevent user to enter specific times in datetimepicker?

I am using angular-bootstrap-datetimepicker. I know how to restrict the user from entering specific dates.
$dates.filter(function(date){
return (date.localDateValue() <= new Date().valueOf()-(24*60*60*1000));
}).forEach(function(date){
date.selectable = false;
})
This code insode startDateBefore render, prevents user from entering dates 24h past the current date.
But now I want users to enter spectic times only. Like user can select only times between 10:05am to 11:10pm. I am unable to do that. Documentation doesn't specify on how to add filter to hour and minutes. Any help on that.
In Angular Date Time Picker, the beforeRender function also takes parameter called view. So we can use the view==='hour' to restrict users from entering past hours. I was missing the code for hours.
function startDateBeforeRender ($view, $dates, $leftDate, $upDate, $rightDate) {
var today = moment().valueOf();
$dates.filter(function (date) {
return date.localDateValue() < today -(24*60*60*1000)
}).forEach(function (date) {
date.selectable = false;
});
// to restrict hours by admin
if ($view === "hour") {
// restict previous hours
$dates.filter(function (date) {
return date.localDateValue() < today
}).forEach(function (date) {
date.selectable = false;
})
}
}
date = new Date().valueOf();
if( date > 1000*(10*60+5) ){
if( date < 1000*(23*60+10) ){
//Code green, I repeat, CODE GREEN!
}
}

Difference between datepickers except sundays in infopath

How to get the no of days between two date picker controls in info path except sundays?
If It is possible let me know.
Thanks in advance.........
Using custom code you can do it easily. In this case I'm calculating the number of days (except Sundays) between a given date and today's date.
var navigator = this.MainDataSource.CreateNavigator();
string startDate = navigator.SelectSingleNode("/my:myFields/my:date_start", NamespaceManager).Value;
DateTime startDateTime = DateTime.ParseExact(startDate, "yyyy-MM-dd", null);
DateTime today = DateTime.Today;
int count = 0;
while (startDateTime > today)
{
today = today.AddDays(1);
if (today.DayOfWeek != DayOfWeek.Sunday)
{
count++;
}
}
I hope it helps