How to convert dates within an array to a specific format - ruby

I have an array of dates, where the dates have different formats. I would like to convert them all to the same format, however what I've tried has caused me some problems.
I get the dates from a SQL query:
table_birth_dates = self.class.connection("SELECT birth_date FROM #{temp_table_name}").values
which gives me an array of dates:
[
[0] "10/3/80",
[1] "10/3/81",
[2] "10/3/01",
[3] "33/33/1970",
]
I want to get the year as a full year like above.
I tried:
table_birth_dates.first.to_time
and got:
ArgumentError: argument out of range
I also tried:
Date.strptime(table_birth_dates)
and got:
no implicit conversion of Array into String
Does anyone have any ideas?

As the others already said: Don't store arbitrary strings as date! Use your database and store dates as date or datetime. See documentation of your database. (See comment from #the-tin-man.)
That said you can try the following with your current date:
table.map! { |date|
date_hash = Date._strptime(date, '%m/%d/%Y') # {:mon=>10, :mday=>3, :year=>70}
if date_hash.nil?
'invalid'
else
date_hash[:year] = date_hash[:year] + 1900 if date_hash[:year] < 1000
Date.new(date_hash[:year], date_hash[:mon], date_hash[:mday])
end
}
This gives you an array with actual dates like so:
[
1980-10-03
1981-10-03
1901-10-03
invalid
]
Of course you should do something about this invalid but it serves your main purpose.

If all you dates is on the the same format as the first 3 dates you can use this con change the format of the dates:
dates.map! do |date|
Date.strptime(date, '%d/%m/%y').strftime('%d/%m/%Y')
end
If you have dates on different formats you could list the formats you have and try to parse each of them and see if you get a valid result, however dates like 33/33/1970 is not a valid date at all.

Parsing dates isn't as straightforward as people assume when they first start working with them, because dates are represented differently around the world.
'10/3/80'
would represent "October 3, 1980" in a U.S. formatted date, but would be "March 10, 1980" in the rest of the world. And, the software has no idea which it is unless you tell it which to use. And, if your data comes from around the world you can't tell unless you know what locale the data was generated in or unless they explicitly tell you what format it's in.
require 'date'
Date.strptime('10/3/80', '%m/%d/%y') # => #<Date: 1980-10-03 ((2444516j,0s,0n),+0s,2299161j)>
Date.strptime('10/3/80', '%d/%m/%y') # => #<Date: 1980-03-10 ((2444309j,0s,0n),+0s,2299161j)>

From DB, bring date in integer format and convert back to any specific format.
Are you storing date in DB as string and trying to convert them for unique format to display? If so, you can correct while storing the value (or) add a column in DB which gets updated whenever your date column gets inserted/updated and retrieve from new column.

Related

Double time specification in file in laravel api

I am making api's in laravel and getting 2021-01-30T10:30:17.704 05:30 from $request->followup and i have column in database named followup having datetime datatype. But it's giving me following error.
Carbon\Exceptions\InvalidFormatException: Could not parse '2021-01-30T10:30:17.704 05:30': DateTime::__construct(): Failed to parse time string (2021-01-30T10:30:17.704 05:30) at position 24 (0): Double time specification in file D:\xampp2\htdocs\synocrm-baid\rest-apis\vendor\nesbot\carbon\src\Carbon\Traits\Creator.php on line 188
I tried to change format like
$followupDate = date('Y-m-d h:i:s A',strtotime($request->followup));
My modal having
#property Carbon|null $followup
$request->followup is appending datetime with datetime
Original Value: 2021-01-30T10:30:17.704 05:30
Datetime: 2021-01-30T10:30:17.704
Time: 05:30
As we can see, there is two Time (05:30 and 10:30:17), because of which the strtotime() cannot convert the value.
In order to fix the problem,
Send the value as time time only (2021-01-30T10:30:17.704) instead of two times Time attribute
If you have no control over request value, you can retrieve only date value like:
$dateValue = explode(' ', $request->followup)[0];
$followupDate = date('Y-m-d h:i:s A',strtotime($dateValue));
Or Using Carbon
$followupDate = Carbon::parse($dateValue);
I would not recommend option 2 because it creates problems and confusion for other devs.
2021-01-30T10:30:17.704 05:30
It does not seem to valid timestamp. For parsing, it should be the valid timestamp or date.

Fill new column with data modified manipulated from data in pre-existing data in another row in Laravel

I have a pre-existing application built with a huge database. In this database, there's a column expires_in that holds a date but the date is saved in this format:
02 Mar 2018 ( i.e. 'd M Y' format)
I want to copy this data into a new column where it will be saved as date in expiration_date column (like this: 2018-03-02 ).
I want to do this in the most efficient way because the database has thousands of records.
Thank you.
Use QueryBuilder's chunk method -- this fetches small subsets of data in a loop. Otherwise with thousands of records, your request could timeout or run out of memory.
You can then use Carbons createFromFormat() method to specify how to parse the current date format and update the record.
Accounts::orderBy('id')->chunk(100, function ($accounts) {
foreach ($accounts as $account) {
$account->update([
'expiration_date' => Carbon::createFromFormat('d M Y', $account->expires_in)
]);
}
});
Found this post about converting string to date
Update `accounts` set `expiration_date` = STR_TO_DATE(expires_in, '%d %M %Y')

Laravel Eloquent date_format Validation fails on given format

I want to create validation rule to validate incoming date.
Format I want to validate is Y-m-d H:i:s. Here's my body request which I am validating:
{ "date":"2015.10.5 10:30:10" }
And here's my validation rule:
'date' => 'required|date_format:"Y.m.d H:i:s"',
And it returns:
{"date":["The date does not match the format Y.m.d H:i:s."]}
If you want to be able to pass the day without a leading zero, then for the day part of your datetime you need to use j instead of d.
'date' => 'required|date_format:"Y.m.j H:i:s"',
That will work for the example you have above.
If you are going to always have a leading zero in your day (so, 05 instead of just 5, then the date format you already have will work.

How to get only first part of the date ('DD') from an entire date?

I've converted a date into string. Now, I want to parse a string to get the DD part from DD-MM-YYYY.
For e.g.
If the date is 03-05-2017 (DD-MM-YYYY) then the goal is to get only first part of the string i.e. 03 (DD).
You've tagged this question as a ServiceNow question, so I assume you're using the ServiceNow GlideDateTime Class to derive the date as a string. If that is correct, did you know that you can actually derive the day of the month directly from the GlideDateTime object? You can use the getDayOfMonth(), getDayOfMonthLocalTime(), or getDayOfMonthUTC().
You could of course, also use String.prototype.indxOf() to get the first hyphen's location, and then return everything up to that location using String.prototype.slice().
Or, if you're certain that the day of the month in the string will contain an initial zero, you can simply .slice() out a new string from index 0 through index 2.
var date = '03-05-2017';
var newDate = date.slice(0, 2);
console.log(newDate); //==>Prints "03".
var alternateNewDate = date.slice(0, date.indexOf('-'));
console.log(alternateNewDate); //==>Prints "03".

Retrieve database records between two weekdays

I have several records in my database, the table has a column named "weekday" where I store a weekday like "mon" or "fri". Now from the frontend when a user does search the parameters posted to the server are startday and endDay.
Now I would like to retrieve all records between startDay and endDay. We can assume startDay is "mon" and endDay is "sun". I do not currently know how to do this.
Create another table with the names of the days and their corresponding number. Then you'd just need to join up your current table with the days table by name, and then use the numbers in that table to do your queries.
Not exactly practical, but it is possible to convert sun,mon,tue to numbers using MySQL.
Setup a static year and week number like 201610 for the 10th week of this year, then use a combination of DATE_FORMAT with STR_TO_DATE:
DATE_FORMAT(STR_TO_DATE('201610 mon', '%X%V %a'), '%w')
DATE_FORMAT(STR_TO_DATE('201610 sun', '%X%V %a'), '%w')
DATE_FORMAT(STR_TO_DATE('201610 tue', '%X%V %a'), '%w')
These 3 statements will evaluate to 0,1,2 respectively.
The main thing this is doing is converting the %a format (Sun-Sat) to the %w format (0-6)
well i don't know the architecture of your application as i think storing and querying a week day string is not appropriate, but i can tell you a work around this.
make a helper function which return you an array of weekdays in the range i-e
function getWeekDaysArray($startWeekDay, $endWeekDay) {
returns $daysArray['mon','tue','wed'];
}
$daysRangeArray = getWeekDaysArray('mon', 'wed');
now with this array you can query in table
DB::table('TableName')->whereIn('week_day', $daysRangeArray)->get();
Hope this help

Resources