Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Time and DateTime typecasting forcing UTC #22

Open
cschiewek opened this issue Jul 25, 2012 · 11 comments
Open

Time and DateTime typecasting forcing UTC #22

cschiewek opened this issue Jul 25, 2012 · 11 comments

Comments

@cschiewek
Copy link

See rubiii/savon#110 for history.

Seems nori is forcing Time objects and DateTime objects to utc when doing typecasting. This causes goes against ISO8601 which clearly states that date and time representations that do not specify a timezone should be considered as being the local time zone.

@cschiewek
Copy link
Author

Closed the pull request as it does not fix the problem.

@rubiii
Copy link
Contributor

rubiii commented Jul 27, 2012

it does not?

@joshco
Copy link

joshco commented Sep 11, 2012

I'm still seeing this problem too.
Im using v 1.1.3
In my XML trace I see:
2012-09-11T17:30:00
In the hash:
:date_begin=>Tue, 11 Sep 2012 17:30:00 +0000

@joshco
Copy link

joshco commented Sep 12, 2012

For any folks struggling with this, I put the following hack in my code:

  def tz_fix(datetime)

    offset=(Time.now.utc_offset/3600).to_s

    dt=datetime.change( :offset => (offset))

   end

Then on any objects I get back I do
e[:date_start]=tz_fix(e[:date_start]

messy but it works

robuye added a commit to robuye/nori that referenced this issue Jun 18, 2013
@Mange
Copy link

Mange commented Mar 31, 2016

Any update on this? I think the code in robuye/nori@505e68f look pretty solid. Is/was it working for you @robuye?

@Mange
Copy link

Mange commented Mar 31, 2016

This hack worked for me in a Rails application. You can substitute with any other implementation.
I'd prefer to have this a lot easier right out of the box (default_to_utc: false option, perhaps?).

config/initializers/nori_overrides.rb

# Make Nori (the XML parser used by wash_out for SOAP API) use Rails' TZ support
module NoriAdvancedTypecastingWithTimeZone
  def advanced_typecasting(value)
    if value.strip =~ Nori::XMLUtilityNode::XS_DATE_TIME
      try_to_convert(value) { |x| Time.zone.parse(x) }
    else
      super
    end
  end
end

class Nori::XMLUtilityNode
  typecasts["dateTime"] = ->(value) { Time.zone.parse(value) if value.present? }
  typecasts["datetime"] = typecasts["dateTime"]

  prepend NoriAdvancedTypecastingWithTimeZone
end

And tests, to make sure my monkey patch does not break / actually works:

  # Nori is used by wash_out to parse SOAP XML into Ruby hashes.
  # We have to patch in Rails' timezone support in an initializer.
  describe "parsing XML using Nori" do
    let(:nori) { Nori.new(advanced_typecasting: true) }

    describe "with type attributes" do
      it "parses dateTimes in the given zone" do
        Time.use_zone("Europe/Helsinki") do # +03:00 in the summer
          result = nori.parse('<time type="datetime">2016-07-07T12:00:10+02:00</time>')
          result["time"].should == Time.zone.parse("2016-07-07T12:00:10+02:00")
        end
      end

      it "defaults dateTimes to Time.zone if no TZ is given" do
        Time.use_zone("Europe/Helsinki") do  # +03:00 in the summer
          result = nori.parse('<time type="datetime">2016-07-07T12:00:10</time>')
          result["time"].should == Time.zone.parse("2016-07-07T12:00:10+03:00")
        end
      end
    end

    describe "without type attribute" do
      it "parses time-like strings in the given zone" do
        Time.use_zone("Europe/Helsinki") do  # +03:00 in the summer
          result = nori.parse("<time>  2016-07-07T12:00:10+02:00  </time>")
          result["time"].should == Time.zone.parse("2016-07-07T12:00:10+02:00")
        end
      end

      it "defaults time-like strings to Time.zone if no TZ is given" do
        Time.use_zone("Europe/Helsinki") do  # +03:00 in the summer
          result = nori.parse("<time>  2016-07-07T12:00:10   </time>")
          result["time"].should == Time.zone.parse("2016-07-07T12:00:10+03:00")
        end
      end
    end
  end

@robuye
Copy link
Contributor

robuye commented Mar 31, 2016

Hi @Mange

I never had this problem myself, simply made a commit to address an existing issue, but I can't confirm if and how it behaves in production environment. I'm also long gone from the project we used Nori (tho afaik it's solid and still in use). I'm not sure I can be of any help here, sorry.

@Mange
Copy link

Mange commented Apr 1, 2016

Thank you for the update, @robuye.

@moiristo
Copy link

moiristo commented May 3, 2019

Thanks for the monkeypatch, @Mange, it works fine! I'm experiencing the same issues with an API that yields timestamps like '2014-01-03T01:00:00'.

I will be using this in production. Is there any chance this will be fixed, or should I create a swanky-nori fork instead?

@Mange
Copy link

Mange commented May 8, 2019

We've been using this in production since this PR was opened and it's worked well for us. You should fork your own copy since we're going to remove our fork shortly as we've been deprecating the SOAP API and are now ready to remove it.

@moiristo
Copy link

moiristo commented May 8, 2019

Alright, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

6 participants