Converting "4:00AM" to ISO8601 - sql

The frontend is sending time values like "4:00AM" or "7:15PM" and I need to convert these to ISO8601 (i.e. "04:00:00" and "19:15:00" respectively) so that I can store them in a "time without time zone" column in PostgreSQL.
What is the easiest way to do this? I have Timex available, and am using Ecto.

Postgres is flexible about date and time formats. You can just cast these strings:
select '4:00AM'::time, '7:15PM'::time
time | time
:------- | :-------
04:00:00 | 19:15:00

In Postgres 'timestamp(tz), date, time(tz), etc` are not stored in a format. Formatting is something you do on retrieval. So:
create table time_test(time_fld time);
insert into time_test values ('4:00AM');
insert into time_test values ('7:15PM');
select time_fld from time_test ;
time_fld
----------
04:00:00
19:15:00
Just pass the string in and let Postgres do the work.

One might manually convert the value to the appropriate Time struct.
iex|1 ▶ [h, m, pm?] =
...|1 ▶ "4:00PM"
...|1 ▶ |> String.downcase()
...|1 ▶ |> String.split(~r/:|(?<=\d)(?=\D)/)
#⇒ ["4", "00", "pm"]
iex|2 ▶ m = String.to_integer(m)
iex|3 ▶ h =
...|3 ▶ if(match?("pm", pm?), do: 12, else: 0) + String.to_integer(h)
#⇒ 16
iex|4 ▶ Time.from_erl!({h, m, 0})
#⇒ ~T[16:00:00]

Related

How to use KQL to format datetime stamp in 'yyyy-MM-ddTHH:mm:ss.fffZ'?

I receive the error format_datetime(): failed to parse format string in argument #2 when trying to format_datetime() using ISO8601 format yyyy-MM-ddTHH:mm:ss.fffZ.
If I leave the T and the Z out, it works,
Surely KQL can format datetimestamps in timezone-aware format. I'm just missing it. I read the docs and it appears that T and Z are not supported formats nor delimiters yet each example in the docs shows the T and Z present(?).
Example:
StorageBlobLogs
| where
AccountName == 'stgtest'
| project
TimeGenerated = format_datetime(TimeGenerated, 'yyyy-MM-ddTHH:mm:ss.fffZ'), //herein lies the issue
AccountName,
RequestBodySize = format_bytes(RequestBodySize)
| sort by TimeGenerated asc
If the code is changed to...
- `TimeGenerated = format_datetime(TimeGenerated, 'yyyy-MM-dd HH:mm:ss.fff')`
...it works, but this is not a timezone-aware timestamp (something I prefer to work in to reduce confusion).
datetime_utc_to_local()
Timezones
I would highly recommend not doing that.
If possible, you would like to let the time zone & format being dealt on the client side.
All datetime values in KQL are UTC. Always.
Even the result of datetime_utc_to_local() is another UTC datetime.
That may lead to (what seems like) unexpected behavior of datetime manipulations (example).
StorageBlobLogs
| sample 10
| project TimeGenerated
| extend Asia_Jerusalem = datetime_utc_to_local(TimeGenerated, "Asia/Jerusalem")
,Europe_London = datetime_utc_to_local(TimeGenerated, "Europe/London")
,Japan = datetime_utc_to_local(TimeGenerated, "Japan")
| extend Asia_Jerusalem_str = format_datetime(Asia_Jerusalem ,"yyyy-MM-dd HH:mm:ss.fff")
,Europe_London_str = format_datetime(Europe_London ,"yyyy-MM-dd HH:mm:ss.fff")
,Japan_str = format_datetime(Japan ,"yyyy-MM-dd HH:mm:ss.fff")
| project-reorder TimeGenerated, Asia_Jerusalem, Asia_Jerusalem_str, Europe_London, Europe_London_str, Japan, Japan_str

How to store an array of date ranges in Postgres?

I am trying to build a schedule, I generate an array of objects on the client containing date ranges
[
{start: "2020-07-06 0:0", end: "2020-07-10 23:59"},
{start: "2020-07-13 0:0", end: "2020-07-17 23:59"}
]
I have a column of type daterange[] what is the proper way to format this data to insert it into my table?
This is what I have so far:
INSERT INTO schedules(owner, name, dates) VALUES (
1,
'work',
'{
{[2020-07-06 0:0,2020-07-10 23:59]},
{[2020-07-13 0:0,2020-07-17 23:59]}
}'
)
I think you want:
insert into schedules(owner, name, dates) values (
1,
'work',
array[
'[2020-07-06, 2020-07-11)'::daterange,
'[2020-07-13, 2020-07-18)'::daterange
]
);
Rationale:
you are using dateranges, so you cannot have time portions (for this, you would need tsrange instead); as your code stands, it seems like you want an inclusive lower bound and an exclusive upper bound (hence [ at the left side, and ) at the right side)
explicit casting is needed so Postgres can recognize the that array elements have the proper datatype (otherwise, they look like text)
then, you can surround the list of ranges with the array[] constructor
Demo on DB Fiddle:
owner | name | dates
----: | :--- | :----------------------------------------------------
1 | work | {"[2020-07-06,2020-07-11)","[2020-07-13,2020-07-18)"}

Django raw sql with datetime

I use postgres for my django project, and for complicated queries to db i use connection.cursor(). Today I have a problem with raw sql query with datetime in filter:
with connection.cursor() as cursor:
cursor.execute(
"SELECT * from orders_orderstatus WHERE datetime > '2017-09-05 16:07:16'"
)
row = [item[0] for item in cursor.fetchall()]
return row
As result we have empty list. But if I query this from psql console, I see that result is not empty:
SELECT * FROM orders_orderstatus WHERE datetime > '2017-09-05 16:07:16';
id | status | datetime
----+--------------------+-------------------------------+
256 | created | 2017-09-05 16:10:59.602091+07
257 | delivered | 2017-09-05 16:11:00.834547+07
258 | created | 2017-09-05 16:11:03.499364+07
Why django doesn't receive this results?
This is show your how python and psql interpret datetime's strings tzinfo.
psql using your string time as UTC.
python send it to db with +hours_of_your_time_zone
If your tz +07 so try in python:
with connection.cursor() as cursor:
cursor.execute(
"SELECT * from orders_orderstatus WHERE datetime > '2017-09-05 09:07:16'"
)
row = [item[0] for item in cursor.fetchall()]
return row
In future try to use datetime objects with tz.
Looks like you have setting:
USE_TZ=True

DateTime conversion error on insert into OrientDB

Error on conversion of date '2014-03-09T02:42:09.893' using the
format: yyyy-MM-dd'T'HH:mm:ss.SSS
The type of error here is com.orientechnologies.orient.core.exception.OQueryParsingException.
I set the DateTime format using:
ALTER DATABASE DATETIMEFORMAT yyyy-MM-dd'T'HH:mm:ss.SSS
Further, I know this is a bug with Orient vs the Node API I use because this also fails in the console:
INSERT INTO User ("settings", "acceptedTerms", "activitiesCount",
"appFirstUseDate", "birthday", "email", "equipment", "feedOption",
"followerCount", "followingCount", "followingFeedLastReadAt",
"gender", "goal", "height_unit", "height_val1", "height_val2",
"kitchenSinkBadgesSeen", "lastRatePrompt", "lastVersionUsed", "level",
"numReferrals", "platform", "popularFeedLastReadAt", "postCount",
"seenHamburgerInstructions", "seenRatePrompt", "stream", "timezone",
"unsubscribedFromWorkoutEmails", "username", "weight", "weight_unit",
"createdAt", "updatedAt", "objectId", "ACL", "sessionToken") VALUES
({"__type":"Pointer","className":"Settings","objectId":"K9X5P470hF"},
true, 10, {"__type":"Date","iso":"2014-03-09T03:37:53.270Z"},
{"__type":"Date","iso":"2000-03-29T00:00:00.000Z"},
"REMOVED#gmail.com", {"1":[6,8,4]}, 1, 0, 0,
{"__type":"Date","iso":"2014-03-12T00:32:11.245Z"}, 2, 2, 1, 5, 3,
["activity","schedule","findfriends","log","share","workouts/new","profile/l8QOwljKWh","editProfile","progress","workouts/today"],
{"__type":"Date","iso":"2014-04-08T22:23:47.799Z"}, "2.4.3", 2, 0, 1,
{"__type":"Date","iso":"2014-04-08T22:23:45.070Z"}, 10, true, true,
"b", "America/Havana", true, "hannah00329", 128, 1,
"2014-03-09T02:42:09.893", "2014-04-08T22:43:27.086", "l8QOwljKWh",
{"*":{"read":true},"l8QOwljKWh":{"read":true,"write":true}},
"t7h4bpx5ri8oyd3vfdt1l7e0b")
With the same error:
Error:
com.orientechnologies.orient.core.exception.OQueryParsingException:
Error on conversion of date '2014-03-09T02:42:09.893' using the
format: yyyy-MM-dd'T'HH:mm:ss.SSS
Most other DateTimes work, but for some reason 1 in every 10000 fails with this error.
The other DateTimes in my table look exactly the same:
2013-06-28T04:50:35.717
2013-07-03T08:16:10.713
2012-12-27T19:56:52.030
EDIT:
Upon further investigation, it looks like 2pm on March 9th is doomsday...
SUCCESS:
2013-06-28T04:50:35.717Z
2013-07-03T08:16:10.713Z
2012-12-27T19:56:52.030Z
ERROR:
2014-03-09T02:42:09.893Z
2014-03-09T02:11:49.764Z
2014-03-09T02:02:43.987Z
2014-03-09T02:10:39.408Z
2014-03-09T02:37:10.196Z
2014-03-09T02:40:46.492Z
2014-03-09T02:22:26.589Z
EDIT:
Here are my OrientDB settings
--------------------------------+----------------------------------------------------+
NAME | VALUE |
--------------------------------+----------------------------------------------------+
Name | null |
Version | 9 |
Date format | yyyy-MM-dd |
Datetime format | yyyy-MM-dd HH:mm:ss |
Timezone | America/Toronto |
Locale Country | US |
Locale Language | en |
Charset | UTF-8 |
Schema RID | #0:1 |
Index Manager RID | #0:2 |
Dictionary RID | null |
--------------------------------+----------------------------------------------------+
2014-03-09T02:00:00 -> 2014-03-09T03:00:00 does not exist when incorporating Daylight Savings Time (DST).
Because that specific time is impossible when using DST, the error was in transferring the data from a database that allowed it to one that didn't. The reason Parse allows it is because they use Coordinated Universal Time (UTC), which does not change with DST.
The fix in OrientDB is as follows:
-- set timezone to utc
ALTER DATABASE TIMEZONE UTC

odbc datetime convertion in erlang

Because of some reason,need convert sql time-stamp YYYY-MM-DD HH:MM:SS into erlang time form {{Y,M,D},{H,M,S}}.
fortunately when I query the database the Return Value is already formed as {{Y,M,D},{H,M,S}}.
like:
[{4,null,null,null,null,
{{2012,12,17},{14,54,4}}, % time-stamp already convert
% from 2012-12-17 14:54:04
0,678,51,61}]
and then also need convert erlang time form {{Y,M,D},{H,M,S}} into SQL time-stamp Form YYYY-MM-DD HH:MM:SS,
after some search there is no such direct function to do it.
so I write the fun like below
my_time() ->
{{Y,Mo,D},{H,Mi, S}} = erlang:localtime(),
TSString =
integer_to_list(Y)++"-"++
integer_to_list(Mo)++"-"++
integer_to_list(D)++" "++
integer_to_list(H) ++ ":" ++
integer_to_list(Mi) ++ ":" ++
integer_to_list(S),
TSString.
It works, but I don't like it. Is there any other way to do this?
Well using lib_io:format() would clean it up a bit:
my_time() ->
{{Y,Mo,D},{H,Mi, S}} = erlang:localtime(),
io_lib:format("~4.10.0B-~2.10.0B-~2.10.0B ~2.10.0B:~2.10.0B:~2.10.0B", [Y, Mo, D, H, Mi, S]).