I am new to elixir and I am trying to find tome tutorials/documentation about parsing decimal to string time. I also need to get the number of the week so I can convert it to YYYY-WW
This is my request body:
%{"time" => 1_481_875_162}
Inspecting it gives me:
IO.inspect data["time"]
#Decimal<1481875172>
With timex, this can be done as follows:
Convert the Decimal to an Integer using Decimal.to_integer/1
Convert the Integer to a DateTime using Timex.from_unix/1
Convert the DateTime to a String formatted the way you want with Timex.format!/2
Since your Decimal is in data["time"], the whole thing would be:
data["time"]
|> Decimal.to_integer
|> Timex.from_unix
|> Timex.format!("{YYYY}-{Wiso}")
Note that I've used the ISO Week Number. Timex also supports other types of week numbers which you can read about here.
You can also use Elixir's built-in DateTime module to convert timestamps into Dates using the from_unix!/2 method (but it currently does not provide a method to get the week number):
iex(1)> DateTime.from_unix!(1_481_875_162)
# => %DateTime{calendar: Calendar.ISO, day: 16, hour: 7, microsecond: {0, 0}, minute: 59, month: 12, second: 22, std_offset: 0, time_zone: "Etc/UTC", utc_offset: 0, year: 2016, zone_abbr: "UTC"}
Related
How can I convert a DataFrame column of strings (in dd/mm/yyyy format) to datetime dtype?
The easiest way is to use to_datetime:
df['col'] = pd.to_datetime(df['col'])
It also offers a dayfirst argument for European times (but beware this isn't strict).
Here it is in action:
In [11]: pd.to_datetime(pd.Series(['05/23/2005']))
Out[11]:
0 2005-05-23 00:00:00
dtype: datetime64[ns]
You can pass a specific format:
In [12]: pd.to_datetime(pd.Series(['05/23/2005']), format="%m/%d/%Y")
Out[12]:
0 2005-05-23
dtype: datetime64[ns]
If your date column is a string of the format '2017-01-01'
you can use pandas astype to convert it to datetime.
df['date'] = df['date'].astype('datetime64[ns]')
or use datetime64[D] if you want Day precision and not nanoseconds
print(type(df_launath['date'].iloc[0]))
yields
<class 'pandas._libs.tslib.Timestamp'>
the same as when you use pandas.to_datetime
You can try it with other formats then '%Y-%m-%d' but at least this works.
You can use the following if you want to specify tricky formats:
df['date_col'] = pd.to_datetime(df['date_col'], format='%d/%m/%Y')
More details on format here:
Python 2 https://docs.python.org/2/library/datetime.html#strftime-strptime-behavior
Python 3 https://docs.python.org/3.7/library/datetime.html#strftime-strptime-behavior
If you have a mixture of formats in your date, don't forget to set infer_datetime_format=True to make life easier.
df['date'] = pd.to_datetime(df['date'], infer_datetime_format=True)
Source: pd.to_datetime
or if you want a customized approach:
def autoconvert_datetime(value):
formats = ['%m/%d/%Y', '%m-%d-%y'] # formats to try
result_format = '%d-%m-%Y' # output format
for dt_format in formats:
try:
dt_obj = datetime.strptime(value, dt_format)
return dt_obj.strftime(result_format)
except Exception as e: # throws exception when format doesn't match
pass
return value # let it be if it doesn't match
df['date'] = df['date'].apply(autoconvert_datetime)
Try this solution:
Change '2022–12–31 00:00:00' to '2022–12–31 00:00:01'
Then run this code: pandas.to_datetime(pandas.Series(['2022–12–31 00:00:01']))
Output: 2022–12–31 00:00:01
Multiple datetime columns
If you want to convert multiple string columns to datetime, then using apply() would be useful.
df[['date1', 'date2']] = df[['date1', 'date2']].apply(pd.to_datetime)
You can pass parameters to to_datetime as kwargs.
df[['start_date', 'end_date']] = df[['start_date', 'end_date']].apply(pd.to_datetime, format="%m/%d/%Y")
Use format= to speed up
If the column contains a time component and you know the format of the datetime/time, then passing the format explicitly would significantly speed up the conversion. There's barely any difference if the column is only date, though. In my project, for a column with 5 millions rows, the difference was huge: ~2.5 min vs 6s.
It turns out explicitly specifying the format is about 25x faster. The following runtime plot shows that there's a huge gap in performance depending on whether you passed format or not.
The code used to produce the plot:
import perfplot
import random
mdYHM = range(1, 13), range(1, 29), range(2000, 2024), range(24), range(60)
perfplot.show(
kernels=[lambda x: pd.to_datetime(x), lambda x: pd.to_datetime(x, format='%m/%d/%Y %H:%M')],
labels=['pd.to_datetime(x)', "pd.to_datetime(x, format='%m/%d/%Y %H:%M')"],
n_range=[2**k for k in range(19)],
setup=lambda n: pd.Series([f"{m}/{d}/{Y} {H}:{M}"
for m,d,Y,H,M in zip(*[random.choices(e, k=n) for e in mdYHM])]),
equality_check=pd.Series.equals,
xlabel='len(df)'
)
This is the time format I want to convert
time = Time.parse('2020-07-02 03:59:59.999 UTC')
#=> 2020-07-02 03:59:59 UTC
I want to convert to string in this format.
"2020-07-02T03:59:59.999Z"
I have tried.
time.strftime("%Y-%m-%dT%H:%M:%S.999Z")
Is this correct? Any better way?
You can just use Time#iso8601 with the desired number of fraction digits as an argument:
time = Time.current.end_of_hour
time.iso8601(3) #=> "2020-07-01T10:59:59.999Z"
If you want to handle the output format explicitly via strftime, there are some things to keep in mind:
Instead of hard-coding 999, you should use %L to get the actual milliseconds:
time = Time.parse('2020-07-02 03:59:59.999 UTC')
#=> 2020-07-02 03:59:59 UTC
time.strftime('%Y-%m-%dT%H:%M:%S.%LZ')
#=> "2020-07-02T03:59:59.999Z"
Use combinations for common formats, e.g. %F for %Y-%m-%d and %T for %H:%M:%S:
time.strftime('%FT%T.%LZ')
#=> "2020-07-02T03:59:59.999Z"
If you are dealing with time zones other than UTC (maybe your machine's local time zone), make sure to convert your time instance to utc first:
time = Time.parse('2020-07-02 05:59:59.999+02:00')
#=> 2020-07-02 05:59:59 +0200
time.utc
#=> 2020-07-02 03:59:59 UTC
time.strftime('%FT%T.%LZ')
#=> "2020-07-02T03:59:59.999Z"
or to use %z / %:z to append the actual time zone offset:
time = Time.parse('2020-07-02 05:59:59.999+02:00')
time.strftime('%FT%T.%L%:z')
#=> "2020-07-02T05:59:59.999+02:00"
For APIs you should use utc.iso8601:
> timestamp = Time.now.utc.iso8601
=> "2015-07-04T21:53:23Z"
See:
https://thoughtbot.com/blog/its-about-time-zones#working-with-apis
sometimes toString(datetime()) return the milliseconds without the leading zeros to reach the length of 3 (yyyy-MM-dd'T'HH:mm:ss.SSSXXX). Is it a bug or normal behavior?
For example:
2019-11-21T15:59:22.53Z -> it should be 2019-11-21T15:59:22.053Z
2019-11-21T15:59:21.216Z -> OK
2019-11-21T15:30:09.042Z -> OK
This behavior causes an issue when I try to convert the string into a date.
Thank you
Try using the apoc.temporal.format function, specifying the iso_instant type conversion.
For example:
RETURN apoc.temporal.format(datetime("2019-11-21T22:04:19.13Z"), 'iso_instant');
will return:
"2019-11-21T22:04:19.130Z"
[UPDATE]
Since the TOSTRING() function is not documented to return any particular ISO 8601 string format for a datetime, one should not depend on it returning a specific format -- or even returning the same string for the same datetime across versions.
However, if you want a non-APOC approach that works with recent versions of neo4j (like, 3.5.12, on which this was tested), here is an example of one way to modify the current TOSTRING() output string to always have a 3-digit millisecond value:
// Generate a string.
// You can play with the number of digits after ".", and
// even eliminate the "." and any following digits.
WITH TOSTRING(datetime("2019-11-21T22:04:10.1Z")) AS d
// Always return a 3-digit millisecond time in result
WITH d, LENGTH(d) AS lth
RETURN d, CASE WHEN lth < 24
THEN SUBSTRING(d, 0, lth-1) + SUBSTRING('.000Z', lth - 20)
ELSE d END AS result
I'm looking for a Delphi (10+) function that returns a TDate with a given year and a week number:
function StartDate(2021, 53): TDate should return 2021-01-01.
While WeekOfTheYear(EncodeDate(2021,1,1)) returns 53 (correct), I can't do the other way round with StartOfAWeek(2021,53, 1) nor StartOfAWeek(2021,53, 5) (5=it's a friday) - it's not recognized as a valid date (=exception). Any suggestions?
Edited:
I'm looking for a ISO 8601 compliant function (like the internal Delphi routines), with Monday=1 and special week consideration (like 2021-01-01), or to be more precise: the "vice versa" routine of WeekOfTheYear
The function you need is:
StartOfAWeek(Year, Week, 1)
You observe that StartOfAWeek(2021, 53, 1) raises an exception. That is correct because 2021 does not have 53 weeks. It only has 52. Week 52 ends on the last day of 2021.
You are getting confused by the result of
WeekOfTheYear(EncodeDate(2021,1,1))
This returns 53, but because the date is at the start of the year, this is week 53 of 2020.
How to return time in RFC 3339 format (2014-06-01T12:00:00Z). I read docs about calendar module, but there was no explanation how to generate time format like this. My program should work in different time zones, so please give me advices.
The Erlang Central page Converting Between struct:time and ISO8601 Format has this example:
Unfortunately, no Erlang libraries provide this functionality. Luckily, the native Erlang date and time formats are very easy to format for display or transmission, even in ISO-8601 format:
-module(iso_fmt).
-export([iso_8601_fmt/1]).
iso_8601_fmt(DateTime) ->
{{Year,Month,Day},{Hour,Min,Sec}} = DateTime,
io_lib:format("~4.10.0B-~2.10.0B-~2.10.0B ~2.10.0B:~2.10.0B:~2.10.0B",
[Year, Month, Day, Hour, Min, Sec]).
format_iso8601() ->
{{Year, Month, Day}, {Hour, Min, Sec}} =
calendar:universal_time(),
iolist_to_binary(
io_lib:format(
"~.4.0w-~.2.0w-~.2.0wT~.2.0w:~.2.0w:~.2.0wZ",
[Year, Month, Day, Hour, Min, Sec] )).
Using the above module:
1> {{Year,Month,Day},{Hour,Min,Sec}} = erlang:localtime().
{{2004,8,28},{1,19,37}}
2> io:fwrite("~s\n",[iso_fmt:iso_8601_fmt(erlang:localtime())]).
2004-08-28 01:48:48
To make it output time in UTC, just pass it the return value of erlang:universaltime() instead of erlang:localtime().