Julian to Gregorian date conversion in Scala - scala

I need to convert Julian date (YYYYDDD) to Gregorian date (YYYYMMDD) in Scala.
I got this far:
import java.text.SimpleDateFormat;
val format1 = new java.text.SimpleDateFormat("yyyyddd")
println(format1.parse("2018022"))
The result is: Mon Jan 22 00:00:00 CST 2018
I need help to get output in "YYYYMMDD" format

See if this does it for you.
import java.text.SimpleDateFormat
val format1 = new SimpleDateFormat("yyyyddd")
new SimpleDateFormat("yyyyMMdd").format(format1.parse("2018022"))
//res0: String = 20180122
Or this, which demonstrates the relationships a little better.
val jDate: String = "2018022"
val gDate: String = new SimpleDateFormat("yyyyMMdd").format(
new SimpleDateFormat("yyyyddd").parse(jDate))

You can use below functions to convert the same. I'am using the same function on my website.
function julian2d($indate) {
$year = substr($indate,0,2);
$day = ltrim(substr($indate,strlen($indate)-3,3),'0'); /* Day part with leading zeroes stripped */
if ($year == 70 && $day == 1) $outdate = 1;
else if ($year == 70) $outdate = ($day-1)*24*60*60;
else if ($year >= 0 && $year <= 99 && $day > 0 && $day <= 366) {
$outdate = strtotime('01-Jan-' . $year); /* Date on Jan 1 of the year */
if ($outdate >= 0) {
$outdate = $outdate + ($day-1)*24*60*60;
} else $outdate = FALSE;
} else $outdate = FALSE;
return $outdate;
}

Related

How to select a week(custom) in the Flutter Date Range Picker (SfDateRangePicker)

I try to implement a weekly selector by following this example - https://www.syncfusion.com/kb/11412/how-to-select-a-week-in-the-flutter-date-range-picker-sfdaterangepicker
The problem I encounter is that the "args.value" from DateRangePickerSelectionChangedArgs returns a date range from Sunday to Saturday. What I want is for the DateRangePickerSelectionChangedArgs to return a date range from Monday to Sunday. I want the weekly selector to select the whole week from Monday to Sunday not from Sunday to Saturday as shown in this screenshot.
enter image description here
I try the codes below. I tried adding one to the start date and to the end date so that Sunday becomes Monday and Saturday becomes Sunday, but the code didn't work when I did that.
void selectionChanged(DateRangePickerSelectionChangedArgs args) {
isSameDate(date1, date2) {
if (date2 == date1) {
return true;
}
if (date1 == null || date2 == null) {
return false;
}
return date1.month == date2.month && date1.year == date2.year && date1.day == date2.day;
}
int firstDayOfWeek = DateTime.sunday % 7;
int endDayOfWeek = (firstDayOfWeek - 1) % 7;
endDayOfWeek = endDayOfWeek < 0 ? 7 + endDayOfWeek : endDayOfWeek;
PickerDateRange ranges = args.value;
DateTime date1 = ranges.startDate!;
DateTime date2 = (ranges.endDate ?? ranges.startDate)!;
if (date1.isAfter(date2)) {
var date = date1;
date1 = date2;
date2 = date;
}
int day1 = date1.weekday % 7;
int day2 = date2.weekday % 7;
DateTime dat1 = date1.add(Duration(days: (firstDayOfWeek - day1) + 1));
DateTime dat2 = date2.add(Duration(days: (endDayOfWeek - day2) + 1));
if (!isSameDate(dat1, date1) || !isSameDate(dat2, date2)) {
datePickerController.selectedRange = PickerDateRange(dat1, dat2);
}
}
You can customize the first day of the week in the date range picker by using the FirstDayofWeek property from the MonthViewSettings. Refer to the UG documentation to know more about FirstDayofWeek,
https://help.syncfusion.com/flutter/daterangepicker/getting-started#change-first-day-of-week
Refer to the code snippets to achieve your requirement,

Date intervals keeping state

My task is to write function, that takes 2 LocalDateTime instances and generate list of intervals, splitted by 15 minutes
case class Interval(start:LocalDateTime, end:LocalDateTime)
so, for example if startDate = 2 Aug 2017 14:30:15 and endDate is 2 Aug 2017 15:00:00, intervals should be
List(Interval(2 Aug 2017 14:30:15, 2 Aug 2017 14:45:15), Interval(2 Aug 2017 14:45:15, 2 Aug 2017 15:00:00))
Here, is 2 main complications(at least for me)
1) If end date is less then prevDate + 15 min, then we need take min from(prevdate + 15 min, endDate)
2) We need somehow keep the state, because start of each interval is end of previous interval.
I am able to create imperative version, but I want to do it in functional style, please, help!)
x => {
var start = x.startTime
var end = min(findRightBorder(start), x.endTime)
var result = ListBuffer(Interval(start, end))
while (end.isBefore(x.endTime)) {
start = end
end = min(start.plusMinutes(QUARTER_MINUTES), x.endTime)
result += Interval(start, end)
}
result.toList
}
private def findRightBorder(dt: LocalDateTime): LocalDateTime = {
val minute = dt.getMinute
if (minute >= 0 && minute < 15) dt.withMinute(15)
else if (minute >= 15 && minute < 30) dt.withMinute(30)
else if (minute >= 30 && minute < 45) dt.withMinute(45)
else if (minute >= 45 && minute < 60) dt.withMinute(0).plusHours(1)
else dt
}
private def min(dt1: LocalDateTime, dt2: LocalDateTime): LocalDateTime = {
if (dt1.compareTo(dt2) < 0) dt1 else dt2
}
Another solution with streams:
x => {
Stream
.from(0)
.map(i => x.startTime.plusMinutes(i * QUARTER_MINUTES))
.takeWhile(_.isBefore(x.endTime))
.map(s => Interval(s, min(s.plusMinutes(QUARTER_MINUTES), x.endTime)))
.toList
}
Here's one way to go about this.
import java.time.LocalDateTime
case class Interval(start:LocalDateTime, end:LocalDateTime)
val dt1: LocalDateTime = ??? //some start DateTime
val dt2: LocalDateTime = ??? //some end DateTime
// a (potentially) infinite Stream of dates at 15 minute intervals
// starting at dt1 but ending before dt2
val dates = Stream.iterate(dt1)(_.plusMinutes(15L))
.takeWhile(_.isBefore(dt2))
val result = dates.sliding(2) //pair the dates together
.toSeq //a Seq is easier to append to
.map{case Seq(from,to) => Interval(from,to)} //make Intervals
.:+(Interval(dates.last,dt2)) //append the final Interval
.toList //if you need a List result

How do you format the day of the month to say “11th”, “21st” or “23rd” in Dart?

I have a date and want to display the date with the suffix th, st, rd, etc.
Here is my dart code.
int year = date.year;
int month = date.month;
int day = date.day;
DateTime dateSelected = new DateTime(year, month, day);
var formatter = new DateFormat('EEEE MMMM dd, yyyy');
displayDate = formatter.format(dateSelected);
This displays dates as "Wednesday April 23, 2014" for example, but I need "Wednesday April 23rd, 2014".
I'm using the intl package.
import 'package:intl/intl.dart';
String getDayOfMonthSuffix(int dayNum) {
if(!(dayNum >= 1 && dayNum <= 31)) {
throw Exception('Invalid day of month');
}
if(dayNum >= 11 && dayNum <= 13) {
return 'th';
}
switch(dayNum % 10) {
case 1: return 'st';
case 2: return 'nd';
case 3: return 'rd';
default: return 'th';
}
}
The above method gets the suffix for you. You can use string concatenation or string interpolation to put together the format you want. e.g
'$day ${getDayOfMonthSuffix(day)}'
Try out this package, Jiffy, inspired by momentjs.
Just simply add the do date pattern. See below
Jiffy([2014, 4, 23]).format("EEEE MMMM do, yyyy"); // Wednesday April 23rd, 2014
You can also add your DateTime object
Jiffy(DateTime(2014, 4, 23)).format("EEEE MMMM do, yyyy"); // Wednesday April 23rd, 2014
I don’t think that there’s build-in functionality for that. You could format the date like that:
format(DateTime date) {
var suffix = "th";
var digit = date.day % 10;
if ((digit > 0 && digit < 4) && (date.day < 11 || date.day > 13)) {
suffix = ["st", "nd", "rd"][digit - 1];
}
return new DateFormat("EEEE MMMM d'$suffix', yyyy").format(date);
}
Note: If you don’t want explicit the '01st' one d is enough.
May not be better...but shorter
static final _dayMap = {1: 'st', 2: 'nd', 3: 'rd'};
static String dayOfMonth(int day) => "$day${_dayMap[day] ?? 'th'}";

How to calculate the time difference between 2 date time values

I am trying to calculate the time difference between 2 date time strings.
I have 2 inputs where the input string is something like this "1:00 PM" and the second one "3:15 PM". I want to know the time difference. So for the above example I want to display 3.15
What I have done:
Converted the time to a 24 hours format. So "1:00 PM" becomes "13:00:00"
Appended the new time to a date like so: new Date("1970-1-1 13:00:00")
Calculated the difference like so:
Code:
var total = Math.round(((new Date("1970-1-1 " + end_time) -
new Date("1970-1-1 " + start_time) ) / 1000 / 3600) , 2 )
But the total is always returning integers and not decimals, so the difference between "1:00 PM" and "3:15 PM" is 2 not 2.15.
I have also tried this (using jQuery, but that is irrelevant):
$('#to_ad,#from_ad').change(function(){
$('#total_ad').val( getDiffTime() );
});
function fixTimeString(time){
var hours = Number(time.match(/^(\d+)/)[1]);
var minutes = Number(time.match(/:(\d+)/)[1]);
var AMPM = time.match(/\s(.*)$/)[1];
if(AMPM == "PM" && hours<12) hours = hours+12;
if(AMPM == "AM" && hours==12) hours = hours-12;
var sHours = hours.toString();
var sMinutes = minutes.toString();
if(hours<10) sHours = "0" + sHours;
if(minutes<10) sMinutes = "0" + sMinutes;
return sHours + ':' + sMinutes + ':00';
}
function getDiffTime(){
var start_time = fixTimeString($('#from_ad').val());
var end_time = fixTimeString($('#to_ad').val());
var start = new Date("1970-1-1 " + end_time).getTime(),
end = new Date("1970-1-1 " + start_time).getTime();
return parseInt(((start - end) / 1000 / 3600, 10)*100) / 100;
}
But the total_ad input is displaying only integer values.
How can I fix this problem?
Math.round rounds to the nearest integer, multiply and divide instead
var start = new Date("1970-1-1 " + start_time).getTime(),
end = new Date("1970-1-1 " + end_time).getTime();
var total = (parseInt(((start-end) / 1000 / 3600)*100, 10)) / 100;
FIDDLE
When you take the time 15:15:00 and subtract 13:00:00, you're left with 2.15 hours, not 3.15, and this example would return 2.15 even without making sure there is only two decimals, but for other times that might not be the case.
You could also use toFixed(2), but that would leave you with 3.00 and not 3 etc.
This is how I calculate it:
calculateDiff();
function calculateDiff(){
_start = "7:00 AM";
_end = "1:00 PM";
_start_time = parseAMDate(_start);
_end_time = parseAMDate(_end);
if (_end_time < _start_time){
_end_time = parseAMDate(_end,1);
}
var difference= _end_time - _start_time;
var hours = Math.floor(difference / 36e5),
minutes = Math.floor(difference % 36e5 / 60000);
if (parseInt(hours) >= 0 ){
if (minutes == 0){
minutes = "00";
}
alert(hours+":"+minutes);
}
}
function parseAMDate(input, next_day) {
var dateReg = /(\d{1,2}):(\d{2})\s*(AM|PM)/;
var hour, minute, result = dateReg.exec(input);
if (result) {
hour = +result[1];
minute = +result[2];
if (result[3] === 'PM' && hour !== 12) {
hour += 12;
}
}
if (!next_day) {
return new Date(1970, 01, 01, hour, minute).getTime();
}else{
return new Date(1970, 01, 02, hour, minute).getTime();
}
}

Perl - Monthly increment loop

I have been using the following code for the last few months, which loops through a period of months from a predefined date until it gets to today's date.
use Date::Pcalc qw(:all);
$startDay = 1;
$startMonth = '4';
$startYear = '2009';
$dateToday = `date +%Y-%m-%d`;
($yt,$mt,$dt) = split(/\-/,$dateToday);
while ($endMonth <= $mt || $startYear < $yt ) {
if ($startMonth eq '12') {
$endMonth = 1;
$endYear = $startYear + 1;
} else {
$endMonth = $startMonth + 1;
$endYear = $startYear;
}
if ($startMonth eq '12') {
$endYear = $startYear + 1;
}
($meYear,$meMonth,$meDay) = Add_Delta_Days($endYear,$endMonth,$startDay,-1);
$endOfMonth = "$meYear-$meMonth-$meDay";
$monthText = Month_to_Text($startMonth);
$startDate = "$startYear-$startMonth-1";
$endDate = "$endYear-$endMonth-1";
print "$startDate - $endDate\n";
if ($startMonth eq '12') {
$startMonth = 1;
$startYear++;
} else {
$startMonth++
}
}
This has been working great for the last few months, but I've realised that now in December, as $endmonth will never be greater $mt (12), this causes an infinite loop.
I've not been able to figure out any alternate way of doing this. I feel like I should be able to fix this relatively easily but I seem to be having severe 'developer's block'
Thanks in advance to anyone who can assist.
my $date = DateTime->new(
time_zone => 'local',
year => $startYear,
month => $startMonth,
day => 1,
);
my $today = DateTime->today(time_zone => 'local');
while ($date <= $today) {
say $date->ymd('-');
$date->add( months => 1 );
}
I think you have a couple of problems with your code. But lets get to the first problem which is the enddate in month 12 which causes a loop in this statement:
while ($endMonth <= $mt || $startYear < $yt ) {
OK what you should do is something like this, once you have the current date, year month and day. You will notice that others have suggested different way to get the current date You should take up this suggestion. However once you have the date this code below should be adopted:
($yt,$mt,$dt) = split(/\-/,$dateToday);
# the line below will create a date like 201212 (yyyy mm) but if the month is a 1 digit month it will place a 0 in front of it to ensure your yymm variable always holds 6 characters in the format of yyyy mm - ok
my $yymm = $yt . ${\(length($mt) == 1 ? '0' : '')} . $mt;
# Now lets check the end date against the yymm
# initialise end date as end_yymm - again it inserts a 0 for single digit month
my $end_yymm = $startyear . ${\(length($startMonth) == 1 ? '0' : '')} . $startMonth;
# the above should get the date as '200904' from your code provide
# the while will check end_yymm like 200904 < 201212 - yes it is...
## the end_yymm will keep getting incremented each month and so will the year component at the end of each year until it reaches 201212
## then the question 201212 < 201212 will cause the while to end
## If you want it go into 201301 then say while ($end_yymm <= $yymm) {
## Hope you get the picture
while ($end_yymm < $yymm) {
if ($startMonth eq '12') {
$endMonth = 1;
$endYear = $startYear + 1;
} else {
$endMonth = $startMonth + 1;
$endYear = $startYear;
}
## Now this one seems to be repeating the endYear calculation as above - to me it seems redundant - maybe get rid of it
if ($startMonth eq '12') {
$endYear = $startYear + 1;
}
## Now that you have the end year and month incremented setup the end_yymm variable again to be picked up in the while statement:
$end_yymm = $startyear . ${\(length($startMonth) == 1 ? '0' : '')} . $startMonth;
# ...... carry on with the rest of your code
} # end the while loop
And that should do it.
All the best