├── Book ├── .gitignore ├── Rakefile ├── README.md ├── generator.rb ├── lib.rb └── SwiftMoment.md ├── SwiftMoment ├── MyPlayground.playground │ ├── Sources │ │ └── SupportCode.swift │ ├── contents.xcplayground │ └── Contents.swift ├── SwiftMomentTests │ ├── LinuxMain.swift │ ├── Info.plist │ ├── DurationTests.swift │ ├── FromNowTests.swift │ ├── XCTestManifests.swift │ ├── ExtensionsTests.swift │ └── MomentTests.swift ├── SwiftMoment │ ├── MomentFromNow.bundle │ │ ├── ar.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── gre.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── sv.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── th.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── Root.plist │ │ ├── ja.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── ko.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── zh-Hant.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── zh-Hans.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── he.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── hu.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── tr.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── tr_TR.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── en.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── en_US.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── vi.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── pt.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── cs.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── da.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── it.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── es.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── lv.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── pt-PT.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── de.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── sk.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── sq.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── nl.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── bg.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── is.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── pl.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── fi.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── fr.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── ms.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── ro.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── nb.lproj │ │ │ └── NSDateTimeAgo.strings │ │ ├── uk.lproj │ │ │ └── NSDateTimeAgo.strings │ │ └── ru.lproj │ │ │ └── NSDateTimeAgo.strings │ ├── SwiftMoment.h │ ├── TimeUnit.swift │ ├── Info.plist │ ├── LazyBox.swift │ ├── MomentCache.swift │ ├── Extensions.swift │ ├── Duration.swift │ ├── Operators.swift │ └── MomentFromNow.swift └── SwiftMoment.xcodeproj │ ├── project.xcworkspace │ └── contents.xcworkspacedata │ └── xcshareddata │ └── xcschemes │ ├── SwiftMoment watchOS.xcscheme │ ├── SwiftMoment iOS.xcscheme │ ├── SwiftMoment tvOS.xcscheme │ └── SwiftMoment macOS.xcscheme ├── .travis.yml ├── .dockerignore ├── Dockerfile ├── SwiftMoment.xcworkspace └── contents.xcworkspacedata ├── .gitignore ├── Package.swift ├── fastlane └── Fastfile ├── .github ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md └── CONTRIBUTING.md ├── Resources └── install_swiftlint.sh ├── LICENSE ├── SwiftMoment.podspec ├── CONTRIBUTORS.md └── README.md /Book/.gitignore: -------------------------------------------------------------------------------- 1 | SwiftMoment.playgroundbook 2 | -------------------------------------------------------------------------------- /SwiftMoment/MyPlayground.playground/Sources/SupportCode.swift: -------------------------------------------------------------------------------- 1 | // empty 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: swift 2 | osx_image: xcode9 3 | 4 | script: 5 | - fastlane ios testLane -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .git/ 2 | .build/ 3 | !.build/checkouts/ 4 | !.build/repositories/ 5 | !.build/workspace-state.json 6 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM swift:4.1 2 | 3 | WORKDIR /package 4 | 5 | COPY . ./ 6 | 7 | RUN swift package resolve 8 | RUN swift package clean 9 | CMD swift test --parallel -------------------------------------------------------------------------------- /SwiftMoment/SwiftMomentTests/LinuxMain.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | import SwiftMomentTests 4 | 5 | var tests = [XCTestCaseEntry]() 6 | tests += __allTests() 7 | XCTMain(tests) -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/ar.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akosma/SwiftMoment/HEAD/SwiftMoment/SwiftMoment/MomentFromNow.bundle/ar.lproj/NSDateTimeAgo.strings -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/gre.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akosma/SwiftMoment/HEAD/SwiftMoment/SwiftMoment/MomentFromNow.bundle/gre.lproj/NSDateTimeAgo.strings -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/sv.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akosma/SwiftMoment/HEAD/SwiftMoment/SwiftMoment/MomentFromNow.bundle/sv.lproj/NSDateTimeAgo.strings -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/th.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akosma/SwiftMoment/HEAD/SwiftMoment/SwiftMoment/MomentFromNow.bundle/th.lproj/NSDateTimeAgo.strings -------------------------------------------------------------------------------- /SwiftMoment.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SwiftMoment/MyPlayground.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Book/Rakefile: -------------------------------------------------------------------------------- 1 | require 'fileutils' 2 | 3 | BOOK = "SwiftMoment.playgroundbook" 4 | 5 | task default: %w[clean book] 6 | 7 | task :clean do 8 | FileUtils.rm_rf(BOOK) if File.exist?(BOOK) 9 | end 10 | 11 | task :book do 12 | ruby "generator.rb --in SwiftMoment.md --out #{BOOK} --verbose" 13 | FileUtils.cp_r '../SwiftMoment/SwiftMoment', BOOK + '/Contents/Sources' 14 | end 15 | 16 | task :test do 17 | ruby "test.rb" 18 | end 19 | 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io 2 | 3 | ### Xcode ### 4 | build/ 5 | *.pbxuser 6 | !default.pbxuser 7 | *.mode1v3 8 | !default.mode1v3 9 | *.mode2v3 10 | !default.mode2v3 11 | *.perspectivev3 12 | !default.perspectivev3 13 | xcuserdata 14 | *.xccheckout 15 | *.moved-aside 16 | DerivedData 17 | *.xcuserstate 18 | 19 | fastlane/report.xml 20 | fastlane/Preview.html 21 | fastlane/screenshots 22 | fastlane/test_output 23 | 24 | 25 | .DS_Store 26 | /.build 27 | /Packages 28 | /*.xcodeproj 29 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/SwiftMoment.h: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftMoment.h 3 | // SwiftMoment 4 | // 5 | // Created by Adrian on 19/01/15. 6 | // Copyright (c) 2015 Adrian Kosmaczewski. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for SwiftMoment. 12 | FOUNDATION_EXPORT double SwiftMomentVersionNumber; 13 | 14 | //! Project version string for SwiftMoment. 15 | FOUNDATION_EXPORT const unsigned char SwiftMomentVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:4.0 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "SwiftMoment", 8 | products: [ 9 | .library(name: "SwiftMoment", targets: ["SwiftMoment"]), 10 | ], 11 | dependencies: [ 12 | // none 13 | ], 14 | targets: [ 15 | .target(name: "SwiftMoment", path: ".", sources: ["SwiftMoment/SwiftMoment"]), 16 | .testTarget(name: "SwiftMomentTests", dependencies: ["SwiftMoment"], path: ".", sources: ["SwiftMoment/SwiftMomentTests"]), 17 | ] 18 | ) 19 | -------------------------------------------------------------------------------- /fastlane/Fastfile: -------------------------------------------------------------------------------- 1 | default_platform :ios 2 | 3 | platform :ios do 4 | desc "Test Lane" 5 | lane :testLane do 6 | xcbuild( 7 | workspace: "SwiftMoment.xcworkspace", 8 | scheme: "SwiftMoment macOS", 9 | clean: true 10 | ) 11 | 12 | xcbuild( 13 | workspace: "SwiftMoment.xcworkspace", 14 | scheme: "SwiftMoment watchOS", 15 | clean: true 16 | ) 17 | 18 | scan( 19 | workspace: "SwiftMoment.xcworkspace", 20 | scheme: "SwiftMoment iOS", 21 | clean: true, 22 | device: "iPhone X" 23 | ) 24 | 25 | scan( 26 | workspace: "SwiftMoment.xcworkspace", 27 | scheme: "SwiftMoment tvOS", 28 | clean: true, 29 | device: "Apple TV 4K" 30 | ) 31 | end 32 | end -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Detailed Description 4 | 6 | 7 | ## Context 8 | 9 | 10 | 11 | ## Possible Implementation 12 | 14 | 15 | ## Your Environment 16 | 18 | * Version used: 19 | * Operating System and version: 20 | * Link to your project: 21 | 22 | -------------------------------------------------------------------------------- /Resources/install_swiftlint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Installs the SwiftLint package. 4 | # Tries to get the precompiled .pkg file from Github, but if that 5 | # fails just recompiles from source. 6 | 7 | set -e 8 | 9 | SWIFTLINT_PKG_PATH="/tmp/SwiftLint.pkg" 10 | SWIFTLINT_PKG_URL="https://github.com/realm/SwiftLint/releases/download/0.10.0/SwiftLint.pkg" 11 | 12 | wget --output-document=$SWIFTLINT_PKG_PATH $SWIFTLINT_PKG_URL 13 | 14 | if [ -f $SWIFTLINT_PKG_PATH ]; then 15 | echo "SwiftLint package exists! Installing it..." 16 | sudo installer -pkg $SWIFTLINT_PKG_PATH -target / 17 | else 18 | echo "SwiftLint package doesn't exist. Compiling from source..." && 19 | git clone https://github.com/realm/SwiftLint.git /tmp/SwiftLint && 20 | cd /tmp/SwiftLint && 21 | git submodule update --init --recursive && 22 | sudo make install 23 | fi 24 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/TimeUnit.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TimeUnit.swift 3 | // SwiftMoment 4 | // 5 | // Created by Adrian on 19/01/15. 6 | // Copyright (c) 2015 Adrian Kosmaczewski. All rights reserved. 7 | // 8 | 9 | /// Represents different time units. 10 | /// 11 | /// - years: Represents year units. 12 | /// - quarters: Represents quarter units. 13 | /// - months: Represents month units. 14 | /// - weeks: Represents week units. 15 | /// - days: Represents day units. 16 | /// - hours: Represents hour units. 17 | /// - minutes: Represents minute units. 18 | /// - seconds: Represents second units. 19 | public enum TimeUnit: String { 20 | case years = "y" 21 | case quarters = "Q" 22 | case months = "M" 23 | case weeks = "w" 24 | case days = "d" 25 | case hours = "H" 26 | case minutes = "m" 27 | case seconds = "s" 28 | } 29 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMomentTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Book/README.md: -------------------------------------------------------------------------------- 1 | # Swift Playgrounds for iPad Book Generator 2 | 3 | This Ruby program parses the Markdown file and generates a Swift 4 | Playgrounds for iPad book (file with the extension .playgroundbook.) 5 | 6 | ## How It Works 7 | 8 | The current version of this program simply generates a book with a 9 | single chapter, separating the pages with horizontal rulers (that is, 10 | the `---` marker in Markdown, which translates as a `
` tag in HTML.) 11 | 12 | It parses the first `

` elements and uses its value as the title of 13 | the chapter. 14 | 15 | Run the `rake` tool to generate the book. 16 | 17 | ## Requirements 18 | 19 | It requires the kramdown and plist gems: 20 | 21 | gem install kramdown 22 | gem install plist 23 | 24 | ## License 25 | 26 | See the LICENSE file in the 27 | [PlaygroundBookGenerator](https://github.com/akosma/PlaygroundBookGenerator) 28 | project in Github. 29 | 30 | -------------------------------------------------------------------------------- /SwiftMoment/MyPlayground.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import SwiftMoment 2 | 3 | let now = moment() 4 | print(now.format()) 5 | 6 | now.second 7 | 8 | var obj = moment([2015, 01, 19, 20, 45, 34])! 9 | obj = obj + 4.days 10 | obj.format("YYYY MMMM dd") 11 | 12 | obj.fromNow() 13 | 14 | var yesterday = moment(locale: Locale(identifier: "ES")) - 2.days 15 | yesterday.fromNow() 16 | 17 | let today = moment() 18 | let first = moment(today).add(50.days) 19 | let second = moment(today).add(50, .days) 20 | 21 | let meierskappel = moment("November 23, 1847")! 22 | let gettysburg = moment("Jul/01/1863")! 23 | let pavon = moment("1861-09-17T10:30:00GMT-4")! 24 | 25 | let moments = [pavon, gettysburg, meierskappel] 26 | let sorted = moments.sorted(by: <) 27 | print(sorted) 28 | 29 | let p = past() 30 | let f = future() 31 | 32 | // Maximum and minimum 33 | let max = maximum(f, now, p) // f, of course 34 | let min = minimum(p, f, now) // p, of course 35 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 0.5 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Book/generator.rb: -------------------------------------------------------------------------------- 1 | # This program parses a Markdown file and 2 | # generates a Swift Playgrounds for iPad book 3 | # (file with the extension .playgroundbook) 4 | # It requires the kramdown and plist gems. 5 | # 6 | # Usage: generator [options] 7 | # -i, --in FILENAME Input in Markdown format 8 | # -o, --out FILENAME Output in Playgroundbook format 9 | # -v, --verbose Toggle verbose mode 10 | # 11 | # Author:: Adrian Kosmaczewski 12 | # Copyright:: Copyright (c) 2016 Adrian Kosmaczewski – All Rights Reserved 13 | # License:: BSD License 14 | 15 | require 'kramdown' 16 | require 'plist' 17 | require 'fileutils' 18 | require 'optparse' 19 | require 'ostruct' 20 | require './lib' 21 | 22 | # Main program 23 | opts = parse_arguments 24 | valid, error_message = validate_options(opts) 25 | if !valid 26 | puts error_message 27 | exit 28 | end 29 | pages = read_input(opts) 30 | create_structure(opts) 31 | 32 | book_manifest = create_book_manifest(opts) 33 | save_book_manifest(opts, book_manifest) 34 | 35 | chapter_manifest = create_chapter_manifest(opts) 36 | create_slides(opts, pages, chapter_manifest) 37 | 38 | puts "Created #{opts.output}" if opts.verbose 39 | puts "Finished" if opts.verbose 40 | 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Adrian Kosmaczewski 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | -------------------------------------------------------------------------------- /SwiftMoment.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | 3 | s.name = "SwiftMoment" 4 | s.version = "0.7" 5 | s.summary = "A time and calendar manipulation library for iOS / macOS / tvOS / watchOS written in Swift" 6 | s.description = <<-DESC 7 | This framework is inspired by Moment.js. Its objectives are the following: 8 | 9 | * Simplify the manipulation and readability of date and interval values. 10 | * Provide help when parsing dates from various string representations. 11 | * Simplifying the formatting of date information into strings. 12 | * Streamlining getting date components (day, month, etc.) from dates and time intervals. 13 | 14 | This framework supports iOS 9+, macOS 10.11+, tvOS 9+, watchOS 3+, Xcode 8 and Swift 3. 15 | DESC 16 | s.homepage = "http://akosma.github.io/SwiftMoment/" 17 | s.license = { :type => "BSD", :file => "LICENSE" } 18 | s.author = { "Adrian Kosmaczewski" => "akosma@me.com" } 19 | s.social_media_url = "http://twitter.com/akosma" 20 | s.ios.deployment_target = "9.0" 21 | s.osx.deployment_target = "10.11" 22 | s.tvos.deployment_target = "9.0" 23 | s.watchos.deployment_target = "3.0" 24 | s.source = { :git => "https://github.com/akosma/SwiftMoment.git", :tag => "v0.7" } 25 | s.source_files = "SwiftMoment/SwiftMoment" 26 | s.resource = "SwiftMoment/SwiftMoment/MomentFromNow.bundle" 27 | end 28 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Description 4 | 5 | 6 | ## Motivation and Context 7 | 8 | 9 | 10 | ## How Has This Been Tested? 11 | 12 | 13 | 14 | 15 | ## Types of changes 16 | 17 | - [ ] Bug fix (non-breaking change which fixes an issue) 18 | - [ ] New feature (non-breaking change which adds functionality) 19 | - [ ] Breaking change (fix or feature that would cause existing functionality to change) 20 | 21 | ## Checklist: 22 | 23 | 24 | - [ ] My code does not leave warnings unattended. 25 | - [ ] My code follows the code style of this project. 26 | - [ ] My change requires a change to the documentation. 27 | - [ ] I have updated the documentation accordingly. 28 | - [ ] I have read the **CONTRIBUTING** document. 29 | - [ ] I have added tests to cover my changes. 30 | - [ ] All new and existing tests passed. 31 | 32 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/LazyBox.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LazyBox.swift 3 | // 4 | // Created by Ole Begemann on 17.12.15. 5 | // Copyright © 2016 Ole Begemann. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | 10 | /// An enumeration used by the LazyBox class. 11 | /// 12 | /// - notYetComputed->T: This value holds a block to be lazily executed. 13 | /// - computed: Indicating that the computation has already happened. 14 | internal enum LazyValue { 15 | case notYetComputed(() -> T) 16 | case computed(T) 17 | } 18 | 19 | 20 | /// Adapted to Swift 3 from 21 | /// https://oleb.net/blog/2015/12/lazy-properties-in-structs-swift/ 22 | internal final class LazyBox { 23 | init(computation: @escaping () -> T) { 24 | val = .notYetComputed(computation) 25 | } 26 | 27 | private var val: LazyValue 28 | 29 | /// All reads and writes of `_value` must happen on this queue. 30 | private let queue = DispatchQueue(label: "LazyBox._value") 31 | 32 | /// Performs the lazy computation, or returns the value stored. 33 | var value: T { 34 | var returnValue: T? = nil 35 | queue.sync { 36 | switch self.val { 37 | case .notYetComputed(let computation): 38 | let result = computation() 39 | self.val = .computed(result) 40 | returnValue = result 41 | case .computed(let result): 42 | returnValue = result 43 | } 44 | } 45 | assert(returnValue != nil) 46 | return returnValue! 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentCache.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MomentCache.swift 3 | // SwiftMoment 4 | // 5 | // Created by Florent Pillet on 08/12/16. 6 | // Copyright © 2016 Adrian Kosmaczewski. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | internal class MomentCache { 12 | // the key we use to cache calendars for a common TimeZone / Locale pair 13 | private struct Key : Hashable, Equatable { 14 | let tz: TimeZone 15 | let locale: Locale 16 | 17 | var hashValue: Int { 18 | return tz.hashValue ^ locale.hashValue 19 | } 20 | static func ==(lhs: Key, rhs: Key) -> Bool { 21 | return lhs.tz == rhs.tz && lhs.locale == rhs.locale 22 | } 23 | } 24 | 25 | // our cache and the lock to access it 26 | private static var calendarCache = [Key:Calendar]() 27 | private static var lock = NSLock() 28 | 29 | // create calendars on demand; in most cases, will return the same calendar 30 | static func calendar(timeZone: TimeZone = defaultTimezone, locale: Locale = defaultLocale) -> Calendar { 31 | lock.lock() 32 | defer { lock.unlock() } 33 | let key = Key(tz: timeZone, locale: locale) 34 | if let calendar = calendarCache[key] { 35 | return calendar 36 | } 37 | var calendar = Calendar.autoupdatingCurrent 38 | calendar.timeZone = timeZone 39 | calendar.locale = locale 40 | calendarCache[key] = calendar 41 | return calendar 42 | } 43 | 44 | static var defaultCalendar : Calendar = { Calendar.autoupdatingCurrent }() 45 | static var defaultLocale : Locale = { Locale.autoupdatingCurrent }() 46 | static var defaultTimezone : TimeZone = { TimeZone.autoupdatingCurrent }() 47 | } 48 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/Root.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | StringsTable 6 | Root 7 | PreferenceSpecifiers 8 | 9 | 10 | Type 11 | PSGroupSpecifier 12 | Title 13 | Group 14 | 15 | 16 | Type 17 | PSTextFieldSpecifier 18 | Title 19 | Name 20 | Key 21 | name_preference 22 | DefaultValue 23 | 24 | IsSecure 25 | 26 | KeyboardType 27 | Alphabet 28 | AutocapitalizationType 29 | None 30 | AutocorrectionType 31 | No 32 | 33 | 34 | Type 35 | PSToggleSwitchSpecifier 36 | Title 37 | Enabled 38 | Key 39 | enabled_preference 40 | DefaultValue 41 | 42 | 43 | 44 | Type 45 | PSSliderSpecifier 46 | Key 47 | slider_preference 48 | DefaultValue 49 | 0.5 50 | MinimumValue 51 | 0 52 | MaximumValue 53 | 1 54 | MinimumValueImage 55 | 56 | MaximumValueImage 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/ja.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- 1 | /* No comment provided by engineer. */ 2 | "%d days ago" = "%d日前"; 3 | 4 | /* No comment provided by engineer. */ 5 | "%d hours ago" = "%d時間前"; 6 | 7 | /* No comment provided by engineer. */ 8 | "%d minutes ago" = "%d分前"; 9 | 10 | /* No comment provided by engineer. */ 11 | "%d months ago" = "%dヶ月前"; 12 | 13 | /* No comment provided by engineer. */ 14 | "%d seconds ago" = "%d秒前"; 15 | 16 | /* No comment provided by engineer. */ 17 | "%d weeks ago" = "%d週間前"; 18 | 19 | /* No comment provided by engineer. */ 20 | "%d years ago" = "%d年前"; 21 | 22 | /* No comment provided by engineer. */ 23 | "A minute ago" = "1分前"; 24 | 25 | /* No comment provided by engineer. */ 26 | "An hour ago" = "1時間前"; 27 | 28 | /* No comment provided by engineer. */ 29 | "Just now" = "たった今"; 30 | 31 | /* No comment provided by engineer. */ 32 | "Last month" = "先月"; 33 | 34 | /* No comment provided by engineer. */ 35 | "Last week" = "先週"; 36 | 37 | /* No comment provided by engineer. */ 38 | "Last year" = "去年"; 39 | 40 | /* No comment provided by engineer. */ 41 | "Yesterday" = "昨日"; 42 | 43 | /* No comment provided by engineer. */ 44 | "1 year ago" = "1年前"; 45 | 46 | /* No comment provided by engineer. */ 47 | "1 month ago" = "1ヶ月前"; 48 | 49 | /* No comment provided by engineer. */ 50 | "1 week ago" = "1週間前"; 51 | 52 | /* No comment provided by engineer. */ 53 | "1 day ago" = "1日前"; 54 | 55 | /* No comment provided by engineer. */ 56 | "This morning" = "午前"; 57 | 58 | /* No comment provided by engineer. */ 59 | "This afternoon" = "午後"; 60 | 61 | /* No comment provided by engineer. */ 62 | "Today" = "今日"; 63 | 64 | /* No comment provided by engineer. */ 65 | "This week" = "今週"; 66 | 67 | /* No comment provided by engineer. */ 68 | "This month" = "今月"; 69 | 70 | /* No comment provided by engineer. */ 71 | "This year" = "今年"; 72 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/ko.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- 1 | /* No comment provided by engineer. */ 2 | "%d days ago" = "%d일전"; 3 | 4 | /* No comment provided by engineer. */ 5 | "%d hours ago" = "%d시간전"; 6 | 7 | /* No comment provided by engineer. */ 8 | "%d minutes ago" = "%d분전"; 9 | 10 | /* No comment provided by engineer. */ 11 | "%d months ago" = "%d개월전"; 12 | 13 | /* No comment provided by engineer. */ 14 | "%d seconds ago" = "%d초전"; 15 | 16 | /* No comment provided by engineer. */ 17 | "%d weeks ago" = "%d주전"; 18 | 19 | /* No comment provided by engineer. */ 20 | "%d years ago" = "%d년전"; 21 | 22 | /* No comment provided by engineer. */ 23 | "A minute ago" = "1분전"; 24 | 25 | /* No comment provided by engineer. */ 26 | "An hour ago" = "1시간전"; 27 | 28 | /* No comment provided by engineer. */ 29 | "Just now" = "방금전"; 30 | 31 | /* No comment provided by engineer. */ 32 | "Last month" = "지난달"; 33 | 34 | /* No comment provided by engineer. */ 35 | "Last week" = "지난주"; 36 | 37 | /* No comment provided by engineer. */ 38 | "Last year" = "지난해"; 39 | 40 | /* No comment provided by engineer. */ 41 | "Yesterday" = "어제"; 42 | 43 | /* No comment provided by engineer. */ 44 | "1 year ago" = "1년전"; 45 | 46 | /* No comment provided by engineer. */ 47 | "1 month ago" = "1개월전"; 48 | 49 | /* No comment provided by engineer. */ 50 | "1 week ago" = "1주전"; 51 | 52 | /* No comment provided by engineer. */ 53 | "1 day ago" = "1일전"; 54 | 55 | /* No comment provided by engineer. */ 56 | "This morning" = "오늘 아침"; 57 | 58 | /* No comment provided by engineer. */ 59 | "This afternoon" = "오늘 오후"; 60 | 61 | /* No comment provided by engineer. */ 62 | "Today" = "오늘"; 63 | 64 | /* No comment provided by engineer. */ 65 | "This week" = "이번주"; 66 | 67 | /* No comment provided by engineer. */ 68 | "This month" = "이번달"; 69 | 70 | /* No comment provided by engineer. */ 71 | "This year" = "올해"; 72 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/zh-Hant.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- 1 | /* No comment provided by engineer. */ 2 | "%d days ago" = "%d天前"; 3 | 4 | /* No comment provided by engineer. */ 5 | "%d hours ago" = "%d小時前"; 6 | 7 | /* No comment provided by engineer. */ 8 | "%d minutes ago" = "%d分鐘前"; 9 | 10 | /* No comment provided by engineer. */ 11 | "%d months ago" = "%d個月前"; 12 | 13 | /* No comment provided by engineer. */ 14 | "%d seconds ago" = "%d秒鐘前"; 15 | 16 | /* No comment provided by engineer. */ 17 | "%d weeks ago" = "%d星期前"; 18 | 19 | /* No comment provided by engineer. */ 20 | "%d years ago" = "%d年前"; 21 | 22 | /* No comment provided by engineer. */ 23 | "A minute ago" = "1分鐘前"; 24 | 25 | /* No comment provided by engineer. */ 26 | "An hour ago" = "1小時前"; 27 | 28 | /* No comment provided by engineer. */ 29 | "Just now" = "剛剛"; 30 | 31 | /* No comment provided by engineer. */ 32 | "Last month" = "上個月"; 33 | 34 | /* No comment provided by engineer. */ 35 | "Last week" = "上星期"; 36 | 37 | /* No comment provided by engineer. */ 38 | "Last year" = "去年"; 39 | 40 | /* No comment provided by engineer. */ 41 | "Yesterday" = "昨天"; 42 | 43 | /* No comment provided by engineer. */ 44 | "1 year ago" = "1年前"; 45 | 46 | /* No comment provided by engineer. */ 47 | "1 month ago" = "1個月前"; 48 | 49 | /* No comment provided by engineer. */ 50 | "1 week ago" = "1星期前"; 51 | 52 | /* No comment provided by engineer. */ 53 | "1 day ago" = "1天前"; 54 | 55 | /* No comment provided by engineer. */ 56 | "This morning" = "今天上午"; 57 | 58 | /* No comment provided by engineer. */ 59 | "This afternoon" = "今天下午"; 60 | 61 | /* No comment provided by engineer. */ 62 | "Today" = "今天"; 63 | 64 | /* No comment provided by engineer. */ 65 | "This week" = "本周"; 66 | 67 | /* No comment provided by engineer. */ 68 | "This month" = "本月"; 69 | 70 | /* No comment provided by engineer. */ 71 | "This year" = "今年"; 72 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/zh-Hans.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- 1 | /* No comment provided by engineer. */ 2 | "%d days ago" = "%d天前"; 3 | 4 | /* No comment provided by engineer. */ 5 | "%d hours ago" = "%d小时前"; 6 | 7 | /* No comment provided by engineer. */ 8 | "%d minutes ago" = "%d分钟前"; 9 | 10 | /* No comment provided by engineer. */ 11 | "%d months ago" = "%d个月前"; 12 | 13 | /* No comment provided by engineer. */ 14 | "%d seconds ago" = "%d秒钟前"; 15 | 16 | /* No comment provided by engineer. */ 17 | "%d weeks ago" = "%d星期前"; 18 | 19 | /* No comment provided by engineer. */ 20 | "%d years ago" = "%d年前"; 21 | 22 | /* No comment provided by engineer. */ 23 | "A minute ago" = "1分钟前"; 24 | 25 | /* No comment provided by engineer. */ 26 | "An hour ago" = "1小时前"; 27 | 28 | /* No comment provided by engineer. */ 29 | "Just now" = "刚刚"; 30 | 31 | /* No comment provided by engineer. */ 32 | "Last month" = "上个月"; 33 | 34 | /* No comment provided by engineer. */ 35 | "Last week" = "上星期"; 36 | 37 | /* No comment provided by engineer. */ 38 | "Last year" = "去年"; 39 | 40 | /* No comment provided by engineer. */ 41 | "Yesterday" = "昨天"; 42 | 43 | /* You can add a space between the number and the characters. */ 44 | "1 year ago" = "1年前"; 45 | 46 | /* You can add a space between the number and the characters. */ 47 | "1 month ago" = "1个月前"; 48 | 49 | /* You can add a space between the number and the characters. */ 50 | "1 week ago" = "1星期前"; 51 | 52 | /* You can add a space between the number and the characters. */ 53 | "1 day ago" = "1天前"; 54 | 55 | /* No comment provided by engineer. */ 56 | "This morning" = "今天上午"; 57 | 58 | /* No comment provided by engineer. */ 59 | "This afternoon" = "今天下午"; 60 | 61 | /* No comment provided by engineer. */ 62 | "Today" = "今天"; 63 | 64 | /* No comment provided by engineer. */ 65 | "This week" = "本周"; 66 | 67 | /* No comment provided by engineer. */ 68 | "This month" = "本月"; 69 | 70 | /* No comment provided by engineer. */ 71 | "This year" = "今年"; 72 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/he.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- 1 | /* No comment provided by engineer. */ 2 | "%d days ago" = "לפני %d ימים"; 3 | 4 | /* No comment provided by engineer. */ 5 | "%d hours ago" = "לפני %d שעות"; 6 | 7 | /* No comment provided by engineer. */ 8 | "%d minutes ago" = "לפני %d דקות"; 9 | 10 | /* No comment provided by engineer. */ 11 | "%d months ago" = "לפני %d חודשים"; 12 | 13 | /* No comment provided by engineer. */ 14 | "%d seconds ago" = "לפני %d שניות"; 15 | 16 | /* No comment provided by engineer. */ 17 | "%d weeks ago" = "לפני %d שבועות"; 18 | 19 | /* No comment provided by engineer. */ 20 | "%d years ago" = "לפני %d שנים"; 21 | 22 | /* No comment provided by engineer. */ 23 | "A minute ago" = "לפני דקה"; 24 | 25 | /* No comment provided by engineer. */ 26 | "An hour ago" = "לפני שעה"; 27 | 28 | /* No comment provided by engineer. */ 29 | "Just now" = "ממש עכשיו"; 30 | 31 | /* No comment provided by engineer. */ 32 | "Last month" = "בחודש שעבר"; 33 | 34 | /* No comment provided by engineer. */ 35 | "Last week" = "בשבוע שעבר"; 36 | 37 | /* No comment provided by engineer. */ 38 | "Last year" = "בשנה שעברה"; 39 | 40 | /* No comment provided by engineer. */ 41 | "Yesterday" = "אתמול"; 42 | 43 | /* No comment provided by engineer. */ 44 | "1 year ago" = "לפני שנה"; 45 | 46 | /* No comment provided by engineer. */ 47 | "1 month ago" = "לפני חודש"; 48 | 49 | /* No comment provided by engineer. */ 50 | "1 week ago" = "לפני שבוע"; 51 | 52 | /* No comment provided by engineer. */ 53 | "1 day ago" = "לפני יום"; 54 | 55 | /* No comment provided by engineer. */ 56 | "This morning" = "הבוקר"; 57 | 58 | /* No comment provided by engineer. */ 59 | "This afternoon" = "בצהריים"; 60 | 61 | /* No comment provided by engineer. */ 62 | "Today" = "היום"; 63 | 64 | /* No comment provided by engineer. */ 65 | "This week" = "השבוע"; 66 | 67 | /* No comment provided by engineer. */ 68 | "This month" = "החודש"; 69 | 70 | /* No comment provided by engineer. */ 71 | "This year" = "השנה"; 72 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/hu.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- 1 | /* No comment provided by engineer. */ 2 | "%d days ago" = "%d napja"; 3 | 4 | /* No comment provided by engineer. */ 5 | "%d hours ago" = "%d órája"; 6 | 7 | /* No comment provided by engineer. */ 8 | "%d minutes ago" = "%d perce"; 9 | 10 | /* No comment provided by engineer. */ 11 | "%d months ago" = "%d hónapja"; 12 | 13 | /* No comment provided by engineer. */ 14 | "%d seconds ago" = "%d másodperce"; 15 | 16 | /* No comment provided by engineer. */ 17 | "%d weeks ago" = "%d hete"; 18 | 19 | /* No comment provided by engineer. */ 20 | "%d years ago" = "%d éve"; 21 | 22 | /* No comment provided by engineer. */ 23 | "A minute ago" = "Egy perccel ezelőtt"; 24 | 25 | /* No comment provided by engineer. */ 26 | "An hour ago" = "Egy órával ezelőtt"; 27 | 28 | /* No comment provided by engineer. */ 29 | "Just now" = "Az imént"; 30 | 31 | /* No comment provided by engineer. */ 32 | "Last month" = "Az előző hónapban"; 33 | 34 | /* No comment provided by engineer. */ 35 | "Last week" = "Az előző héten"; 36 | 37 | /* No comment provided by engineer. */ 38 | "Last year" = "Tavaly"; 39 | 40 | /* No comment provided by engineer. */ 41 | "Yesterday" = "Tegnap"; 42 | 43 | /* No comment provided by engineer. */ 44 | "1 year ago" = "Tavaly"; 45 | 46 | /* No comment provided by engineer. */ 47 | "1 month ago" = "Egy hónapja"; 48 | 49 | /* No comment provided by engineer. */ 50 | "1 week ago" = "Egy hete"; 51 | 52 | /* No comment provided by engineer. */ 53 | "1 day ago" = "Tegnap"; 54 | 55 | /* No comment provided by engineer. */ 56 | "This morning" = "Ma reggel"; 57 | 58 | /* No comment provided by engineer. */ 59 | "This afternoon" = "Ma délután"; 60 | 61 | /* No comment provided by engineer. */ 62 | "Today" = "Ma"; 63 | 64 | /* No comment provided by engineer. */ 65 | "This week" = "Ezen a héten"; 66 | 67 | /* No comment provided by engineer. */ 68 | "This month" = "Ebben a hónapban"; 69 | 70 | /* No comment provided by engineer. */ 71 | "This year" = "Idén"; 72 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/tr.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- 1 | /* No comment provided by engineer. */ 2 | "%d days ago" = "%d gün önce"; 3 | 4 | /* No comment provided by engineer. */ 5 | "%d hours ago" = "%d saat önce"; 6 | 7 | /* No comment provided by engineer. */ 8 | "%d minutes ago" = "%d dakika önce"; 9 | 10 | /* No comment provided by engineer. */ 11 | "%d months ago" = "%d ay önce"; 12 | 13 | /* No comment provided by engineer. */ 14 | "%d seconds ago" = "%d saniye önce"; 15 | 16 | /* No comment provided by engineer. */ 17 | "%d weeks ago" = "%d hafta önce"; 18 | 19 | /* No comment provided by engineer. */ 20 | "%d years ago" = "%d yıl önce"; 21 | 22 | /* No comment provided by engineer. */ 23 | "A minute ago" = "Bir dakika önce"; 24 | 25 | /* No comment provided by engineer. */ 26 | "An hour ago" = "Bir saat önce"; 27 | 28 | /* No comment provided by engineer. */ 29 | "Just now" = "Şimdi"; 30 | 31 | /* No comment provided by engineer. */ 32 | "Last month" = "Geçen ay"; 33 | 34 | /* No comment provided by engineer. */ 35 | "Last week" = "Geçen hafta"; 36 | 37 | /* No comment provided by engineer. */ 38 | "Last year" = "Geçen yıl"; 39 | 40 | /* No comment provided by engineer. */ 41 | "Yesterday" = "Dün"; 42 | 43 | /* No comment provided by engineer. */ 44 | "1 year ago" = "1 yıl önce"; 45 | 46 | /* No comment provided by engineer. */ 47 | "1 month ago" = "1 ay önce"; 48 | 49 | /* No comment provided by engineer. */ 50 | "1 week ago" = "1 hafta önce"; 51 | 52 | /* No comment provided by engineer. */ 53 | "1 day ago" = "1 gün önce"; 54 | 55 | /* No comment provided by engineer. */ 56 | "This morning" = "Bu sabah"; 57 | 58 | /* No comment provided by engineer. */ 59 | "This afternoon" = "Öğleden sonra"; 60 | 61 | /* No comment provided by engineer. */ 62 | "Today" = "Bugün"; 63 | 64 | /* No comment provided by engineer. */ 65 | "This week" = "Bu hafta"; 66 | 67 | /* No comment provided by engineer. */ 68 | "This month" = "Bu ay"; 69 | 70 | /* No comment provided by engineer. */ 71 | "This year" = "Bu yıl"; 72 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/tr_TR.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- 1 | /* No comment provided by engineer. */ 2 | "%d days ago" = "%d gün önce"; 3 | 4 | /* No comment provided by engineer. */ 5 | "%d hours ago" = "%d saat önce"; 6 | 7 | /* No comment provided by engineer. */ 8 | "%d minutes ago" = "%d dakika önce"; 9 | 10 | /* No comment provided by engineer. */ 11 | "%d months ago" = "%d ay önce"; 12 | 13 | /* No comment provided by engineer. */ 14 | "%d seconds ago" = "%d saniye önce"; 15 | 16 | /* No comment provided by engineer. */ 17 | "%d weeks ago" = "%d hafta önce"; 18 | 19 | /* No comment provided by engineer. */ 20 | "%d years ago" = "%d yıl önce"; 21 | 22 | /* No comment provided by engineer. */ 23 | "A minute ago" = "Bir dakika önce"; 24 | 25 | /* No comment provided by engineer. */ 26 | "An hour ago" = "Bir saat önce"; 27 | 28 | /* No comment provided by engineer. */ 29 | "Just now" = "Şimdi"; 30 | 31 | /* No comment provided by engineer. */ 32 | "Last month" = "Geçen ay"; 33 | 34 | /* No comment provided by engineer. */ 35 | "Last week" = "Geçen hafta"; 36 | 37 | /* No comment provided by engineer. */ 38 | "Last year" = "Geçen yıl"; 39 | 40 | /* No comment provided by engineer. */ 41 | "Yesterday" = "Dün"; 42 | 43 | /* No comment provided by engineer. */ 44 | "1 year ago" = "1 yıl önce"; 45 | 46 | /* No comment provided by engineer. */ 47 | "1 month ago" = "1 ay önce"; 48 | 49 | /* No comment provided by engineer. */ 50 | "1 week ago" = "1 hafta önce"; 51 | 52 | /* No comment provided by engineer. */ 53 | "1 day ago" = "1 gün önce"; 54 | 55 | /* No comment provided by engineer. */ 56 | "This morning" = "Bu sabah"; 57 | 58 | /* No comment provided by engineer. */ 59 | "This afternoon" = "Öğleden sonra"; 60 | 61 | /* No comment provided by engineer. */ 62 | "Today" = "Bugün"; 63 | 64 | /* No comment provided by engineer. */ 65 | "This week" = "Bu hafta"; 66 | 67 | /* No comment provided by engineer. */ 68 | "This month" = "Bu ay"; 69 | 70 | /* No comment provided by engineer. */ 71 | "This year" = "Bu yıl"; 72 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/en.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- 1 | /* No comment provided by engineer. */ 2 | "%d days ago" = "%d days ago"; 3 | 4 | /* No comment provided by engineer. */ 5 | "%d hours ago" = "%d hours ago"; 6 | 7 | /* No comment provided by engineer. */ 8 | "%d minutes ago" = "%d minutes ago"; 9 | 10 | /* No comment provided by engineer. */ 11 | "%d months ago" = "%d months ago"; 12 | 13 | /* No comment provided by engineer. */ 14 | "%d seconds ago" = "%d seconds ago"; 15 | 16 | /* No comment provided by engineer. */ 17 | "%d weeks ago" = "%d weeks ago"; 18 | 19 | /* No comment provided by engineer. */ 20 | "%d years ago" = "%d years ago"; 21 | 22 | /* No comment provided by engineer. */ 23 | "A minute ago" = "A minute ago"; 24 | 25 | /* No comment provided by engineer. */ 26 | "An hour ago" = "An hour ago"; 27 | 28 | /* No comment provided by engineer. */ 29 | "Just now" = "Just now"; 30 | 31 | /* No comment provided by engineer. */ 32 | "Last month" = "Last month"; 33 | 34 | /* No comment provided by engineer. */ 35 | "Last week" = "Last week"; 36 | 37 | /* No comment provided by engineer. */ 38 | "Last year" = "Last year"; 39 | 40 | /* No comment provided by engineer. */ 41 | "Yesterday" = "Yesterday"; 42 | 43 | /* No comment provided by engineer. */ 44 | "1 year ago" = "1 year ago"; 45 | 46 | /* No comment provided by engineer. */ 47 | "1 month ago" = "1 month ago"; 48 | 49 | /* No comment provided by engineer. */ 50 | "1 week ago" = "1 week ago"; 51 | 52 | /* No comment provided by engineer. */ 53 | "1 day ago" = "1 day ago"; 54 | 55 | /* No comment provided by engineer. */ 56 | "This morning" = "This morning"; 57 | 58 | /* No comment provided by engineer. */ 59 | "This afternoon" = "This afternoon"; 60 | 61 | /* No comment provided by engineer. */ 62 | "Today" = "Today"; 63 | 64 | /* No comment provided by engineer. */ 65 | "This week" = "This week"; 66 | 67 | /* No comment provided by engineer. */ 68 | "This month" = "This month"; 69 | 70 | /* No comment provided by engineer. */ 71 | "This year" = "This year"; 72 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/en_US.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- 1 | /* No comment provided by engineer. */ 2 | "%d days ago" = "%d days ago"; 3 | 4 | /* No comment provided by engineer. */ 5 | "%d hours ago" = "%d hours ago"; 6 | 7 | /* No comment provided by engineer. */ 8 | "%d minutes ago" = "%d minutes ago"; 9 | 10 | /* No comment provided by engineer. */ 11 | "%d months ago" = "%d months ago"; 12 | 13 | /* No comment provided by engineer. */ 14 | "%d seconds ago" = "%d seconds ago"; 15 | 16 | /* No comment provided by engineer. */ 17 | "%d weeks ago" = "%d weeks ago"; 18 | 19 | /* No comment provided by engineer. */ 20 | "%d years ago" = "%d years ago"; 21 | 22 | /* No comment provided by engineer. */ 23 | "A minute ago" = "A minute ago"; 24 | 25 | /* No comment provided by engineer. */ 26 | "An hour ago" = "An hour ago"; 27 | 28 | /* No comment provided by engineer. */ 29 | "Just now" = "Just now"; 30 | 31 | /* No comment provided by engineer. */ 32 | "Last month" = "Last month"; 33 | 34 | /* No comment provided by engineer. */ 35 | "Last week" = "Last week"; 36 | 37 | /* No comment provided by engineer. */ 38 | "Last year" = "Last year"; 39 | 40 | /* No comment provided by engineer. */ 41 | "Yesterday" = "Yesterday"; 42 | 43 | /* No comment provided by engineer. */ 44 | "1 year ago" = "1 year ago"; 45 | 46 | /* No comment provided by engineer. */ 47 | "1 month ago" = "1 month ago"; 48 | 49 | /* No comment provided by engineer. */ 50 | "1 week ago" = "1 week ago"; 51 | 52 | /* No comment provided by engineer. */ 53 | "1 day ago" = "1 day ago"; 54 | 55 | /* No comment provided by engineer. */ 56 | "This morning" = "This morning"; 57 | 58 | /* No comment provided by engineer. */ 59 | "This afternoon" = "This afternoon"; 60 | 61 | /* No comment provided by engineer. */ 62 | "Today" = "Today"; 63 | 64 | /* No comment provided by engineer. */ 65 | "This week" = "This week"; 66 | 67 | /* No comment provided by engineer. */ 68 | "This month" = "This month"; 69 | 70 | /* No comment provided by engineer. */ 71 | "This year" = "This year"; 72 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/vi.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- 1 | /* No comment provided by engineer. */ 2 | "%d days ago" = "%d ngày trước"; 3 | 4 | /* No comment provided by engineer. */ 5 | "%d hours ago" = "%d giờ trước"; 6 | 7 | /* No comment provided by engineer. */ 8 | "%d minutes ago" = "%d phút trước"; 9 | 10 | /* No comment provided by engineer. */ 11 | "%d months ago" = "%d tháng trước"; 12 | 13 | /* No comment provided by engineer. */ 14 | "%d seconds ago" = "%d giây trước"; 15 | 16 | /* No comment provided by engineer. */ 17 | "%d weeks ago" = "%d tuần trước"; 18 | 19 | /* No comment provided by engineer. */ 20 | "%d years ago" = "%d năm trước"; 21 | 22 | /* No comment provided by engineer. */ 23 | "A minute ago" = "Một phút trước"; 24 | 25 | /* No comment provided by engineer. */ 26 | "An hour ago" = "Một giờ trước"; 27 | 28 | /* No comment provided by engineer. */ 29 | "Just now" = "Vừa mới đây"; 30 | 31 | /* No comment provided by engineer. */ 32 | "Last month" = "Tháng trước"; 33 | 34 | /* No comment provided by engineer. */ 35 | "Last week" = "Tuần trước"; 36 | 37 | /* No comment provided by engineer. */ 38 | "Last year" = "Năm vừa rồi"; 39 | 40 | /* No comment provided by engineer. */ 41 | "Yesterday" = "Hôm qua"; 42 | 43 | /* No comment provided by engineer. */ 44 | "1 year ago" = "1 năm trước"; 45 | 46 | /* No comment provided by engineer. */ 47 | "1 month ago" = "1 tháng trước"; 48 | 49 | /* No comment provided by engineer. */ 50 | "1 week ago" = "1 tuần trước"; 51 | 52 | /* No comment provided by engineer. */ 53 | "1 day ago" = "1 ngày trước"; 54 | 55 | /* No comment provided by engineer. */ 56 | "This morning" = "Sáng nay"; 57 | 58 | /* No comment provided by engineer. */ 59 | "This afternoon" = "Trưa nay"; 60 | 61 | /* No comment provided by engineer. */ 62 | "Today" = "Hôm nay"; 63 | 64 | /* No comment provided by engineer. */ 65 | "This week" = "Tuần này"; 66 | 67 | /* No comment provided by engineer. */ 68 | "This month" = "Tháng này"; 69 | 70 | /* No comment provided by engineer. */ 71 | "This year" = "Năm nay"; 72 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/pt.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- 1 | /* No comment provided by engineer. */ 2 | "%d days ago" = "%d dias atrás"; 3 | 4 | /* No comment provided by engineer. */ 5 | "%d hours ago" = "%d horas atrás"; 6 | 7 | /* No comment provided by engineer. */ 8 | "%d minutes ago" = "%d minutos atrás"; 9 | 10 | /* No comment provided by engineer. */ 11 | "%d months ago" = "%d meses atrás"; 12 | 13 | /* No comment provided by engineer. */ 14 | "%d seconds ago" = "%d segundos atrás"; 15 | 16 | /* No comment provided by engineer. */ 17 | "%d weeks ago" = "%d semanas atrás"; 18 | 19 | /* No comment provided by engineer. */ 20 | "%d years ago" = "%d anos atrás"; 21 | 22 | /* No comment provided by engineer. */ 23 | "A minute ago" = "Há um minuto"; 24 | 25 | /* No comment provided by engineer. */ 26 | "An hour ago" = "Há uma hora"; 27 | 28 | /* No comment provided by engineer. */ 29 | "Just now" = "Agora"; 30 | 31 | /* No comment provided by engineer. */ 32 | "Last month" = "Mês passado"; 33 | 34 | /* No comment provided by engineer. */ 35 | "Last week" = "Semana passada"; 36 | 37 | /* No comment provided by engineer. */ 38 | "Last year" = "Ano passado"; 39 | 40 | /* No comment provided by engineer. */ 41 | "Yesterday" = "Ontem"; 42 | 43 | /* No comment provided by engineer. */ 44 | "1 year ago" = "1 ano atrás"; 45 | 46 | /* No comment provided by engineer. */ 47 | "1 month ago" = "1 mês atrás"; 48 | 49 | /* No comment provided by engineer. */ 50 | "1 week ago" = "1 semana atrás"; 51 | 52 | /* No comment provided by engineer. */ 53 | "1 day ago" = "1 dia atrás"; 54 | 55 | /* No comment provided by engineer. */ 56 | "This morning" = "Esta manhã"; 57 | 58 | /* No comment provided by engineer. */ 59 | "This afternoon" = "Esta tarde"; 60 | 61 | /* No comment provided by engineer. */ 62 | "Today" = "Hoje"; 63 | 64 | /* No comment provided by engineer. */ 65 | "This week" = "Esta semana"; 66 | 67 | /* No comment provided by engineer. */ 68 | "This month" = "Este mês"; 69 | 70 | /* No comment provided by engineer. */ 71 | "This year" = "Este ano"; 72 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/cs.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- 1 | /* No comment provided by engineer. */ 2 | "%d days ago" = "Před %d dny"; 3 | 4 | /* No comment provided by engineer. */ 5 | "%d hours ago" = "Před %d hodinami"; 6 | 7 | /* No comment provided by engineer. */ 8 | "%d minutes ago" = "Před %d minutami"; 9 | 10 | /* No comment provided by engineer. */ 11 | "%d months ago" = "Před %d měsíci"; 12 | 13 | /* No comment provided by engineer. */ 14 | "%d seconds ago" = "Před %d sekundami"; 15 | 16 | /* No comment provided by engineer. */ 17 | "%d weeks ago" = "Před %d týdny"; 18 | 19 | /* No comment provided by engineer. */ 20 | "%d years ago" = "Před %d lety"; 21 | 22 | /* No comment provided by engineer. */ 23 | "A minute ago" = "Před minutou"; 24 | 25 | /* No comment provided by engineer. */ 26 | "An hour ago" = "Před hodinou"; 27 | 28 | /* No comment provided by engineer. */ 29 | "Just now" = "Právě teď"; 30 | 31 | /* No comment provided by engineer. */ 32 | "Last month" = "Minulý měsíc"; 33 | 34 | /* No comment provided by engineer. */ 35 | "Last week" = "Minulý týden"; 36 | 37 | /* No comment provided by engineer. */ 38 | "Last year" = "Minulý rok"; 39 | 40 | /* No comment provided by engineer. */ 41 | "Yesterday" = "Včera"; 42 | 43 | /* No comment provided by engineer. */ 44 | "1 year ago" = "Před rokem"; 45 | 46 | /* No comment provided by engineer. */ 47 | "1 month ago" = "Před měsícem"; 48 | 49 | /* No comment provided by engineer. */ 50 | "1 week ago" = "Před týdnem"; 51 | 52 | /* No comment provided by engineer. */ 53 | "1 day ago" = "Předevčírem"; 54 | 55 | /* No comment provided by engineer. */ 56 | "This morning" = "Dnes dopoledne"; 57 | 58 | /* No comment provided by engineer. */ 59 | "This afternoon" = "Dnes odpoledne"; 60 | 61 | /* No comment provided by engineer. */ 62 | "Today" = "Dnes"; 63 | 64 | /* No comment provided by engineer. */ 65 | "This week" = "Tento týden"; 66 | 67 | /* No comment provided by engineer. */ 68 | "This month" = "Tento měsíc"; 69 | 70 | /* No comment provided by engineer. */ 71 | "This year" = "Letos"; 72 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/da.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- 1 | /* No comment provided by engineer. */ 2 | "%d days ago" = "%d dage siden"; 3 | 4 | /* No comment provided by engineer. */ 5 | "%d hours ago" = "%d timer siden"; 6 | 7 | /* No comment provided by engineer. */ 8 | "%d minutes ago" = "%d minutter siden"; 9 | 10 | /* No comment provided by engineer. */ 11 | "%d months ago" = "%d måneder siden"; 12 | 13 | /* No comment provided by engineer. */ 14 | "%d seconds ago" = "%d sekunder siden"; 15 | 16 | /* No comment provided by engineer. */ 17 | "%d weeks ago" = "%d uger siden"; 18 | 19 | /* No comment provided by engineer. */ 20 | "%d years ago" = "%d år siden"; 21 | 22 | /* No comment provided by engineer. */ 23 | "A minute ago" = "Et minut siden"; 24 | 25 | /* No comment provided by engineer. */ 26 | "An hour ago" = "En time siden"; 27 | 28 | /* No comment provided by engineer. */ 29 | "Just now" = "Lige nu"; 30 | 31 | /* No comment provided by engineer. */ 32 | "Last month" = "Sidste måned"; 33 | 34 | /* No comment provided by engineer. */ 35 | "Last week" = "Sidste uge"; 36 | 37 | /* No comment provided by engineer. */ 38 | "Last year" = "Sidste år"; 39 | 40 | /* No comment provided by engineer. */ 41 | "Yesterday" = "I går"; 42 | 43 | /* No comment provided by engineer. */ 44 | "1 year ago" = "1 år siden"; 45 | 46 | /* No comment provided by engineer. */ 47 | "1 month ago" = "1 måned siden"; 48 | 49 | /* No comment provided by engineer. */ 50 | "1 week ago" = "1 uge siden"; 51 | 52 | /* No comment provided by engineer. */ 53 | "1 day ago" = "1 dag siden"; 54 | 55 | /* No comment provided by engineer. */ 56 | "This morning" = "Her til morgen"; 57 | 58 | /* No comment provided by engineer. */ 59 | "This afternoon" = "Her til eftermiddag"; 60 | 61 | /* No comment provided by engineer. */ 62 | "Today" = "I dag"; 63 | 64 | /* No comment provided by engineer. */ 65 | "This week" = "Denne uge"; 66 | 67 | /* No comment provided by engineer. */ 68 | "This month" = "Denne måned"; 69 | 70 | /* No comment provided by engineer. */ 71 | "This year" = "Dette år"; -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/it.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- 1 | /* No comment provided by engineer. */ 2 | "%d days ago" = "%d giorni fa"; 3 | 4 | /* No comment provided by engineer. */ 5 | "%d hours ago" = "%d ore fa"; 6 | 7 | /* No comment provided by engineer. */ 8 | "%d minutes ago" = "%d minuti fa"; 9 | 10 | /* No comment provided by engineer. */ 11 | "%d months ago" = "%d mesi fa"; 12 | 13 | /* No comment provided by engineer. */ 14 | "%d seconds ago" = "%d secondi fa"; 15 | 16 | /* No comment provided by engineer. */ 17 | "%d weeks ago" = "%d settimane fa"; 18 | 19 | /* No comment provided by engineer. */ 20 | "%d years ago" = "%d anni fa"; 21 | 22 | /* No comment provided by engineer. */ 23 | "A minute ago" = "Un minuto fa"; 24 | 25 | /* No comment provided by engineer. */ 26 | "An hour ago" = "Un'ora fa"; 27 | 28 | /* No comment provided by engineer. */ 29 | "Just now" = "Ora"; 30 | 31 | /* No comment provided by engineer. */ 32 | "Last month" = "Il mese scorso"; 33 | 34 | /* No comment provided by engineer. */ 35 | "Last week" = "La settimana scorsa"; 36 | 37 | /* No comment provided by engineer. */ 38 | "Last year" = "L'anno scorso"; 39 | 40 | /* No comment provided by engineer. */ 41 | "Yesterday" = "Ieri"; 42 | 43 | /* No comment provided by engineer. */ 44 | "1 year ago" = "Un anno fa"; 45 | 46 | /* No comment provided by engineer. */ 47 | "1 month ago" = "Un mese fa"; 48 | 49 | /* No comment provided by engineer. */ 50 | "1 week ago" = "Una settimana fa"; 51 | 52 | /* No comment provided by engineer. */ 53 | "1 day ago" = "Un giorno fa"; 54 | 55 | /* No comment provided by engineer. */ 56 | "This morning" = "Questa mattina"; 57 | 58 | /* No comment provided by engineer. */ 59 | "This afternoon" = "Questo pomeriggio"; 60 | 61 | /* No comment provided by engineer. */ 62 | "Today" = "Oggi"; 63 | 64 | /* No comment provided by engineer. */ 65 | "This week" = "Questa settimana"; 66 | 67 | /* No comment provided by engineer. */ 68 | "This month" = "Questo mese"; 69 | 70 | /* No comment provided by engineer. */ 71 | "This year" = "Quest'anno"; 72 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/es.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- 1 | /* No comment provided by engineer. */ 2 | "%d days ago" = "Hace %d días"; 3 | 4 | /* No comment provided by engineer. */ 5 | "%d hours ago" = "Hace %d horas"; 6 | 7 | /* No comment provided by engineer. */ 8 | "%d minutes ago" = "Hace %d minutos"; 9 | 10 | /* No comment provided by engineer. */ 11 | "%d months ago" = "Hace %d meses"; 12 | 13 | /* No comment provided by engineer. */ 14 | "%d seconds ago" = "Hace %d segundos"; 15 | 16 | /* No comment provided by engineer. */ 17 | "%d weeks ago" = "Hace %d semanas"; 18 | 19 | /* No comment provided by engineer. */ 20 | "%d years ago" = "Hace %d años"; 21 | 22 | /* No comment provided by engineer. */ 23 | "A minute ago" = "Hace un minuto"; 24 | 25 | /* No comment provided by engineer. */ 26 | "An hour ago" = "Hace una hora"; 27 | 28 | /* No comment provided by engineer. */ 29 | "Just now" = "Ahora mismo"; 30 | 31 | /* No comment provided by engineer. */ 32 | "Last month" = "El mes pasado"; 33 | 34 | /* No comment provided by engineer. */ 35 | "Last week" = "La semana pasada"; 36 | 37 | /* No comment provided by engineer. */ 38 | "Last year" = "El año pasado"; 39 | 40 | /* No comment provided by engineer. */ 41 | "Yesterday" = "Ayer"; 42 | 43 | /* No comment provided by engineer. */ 44 | "1 year ago" = "Hace un año"; 45 | 46 | /* No comment provided by engineer. */ 47 | "1 month ago" = "Hace un mes"; 48 | 49 | /* No comment provided by engineer. */ 50 | "1 week ago" = "Hace una semana"; 51 | 52 | /* No comment provided by engineer. */ 53 | "1 day ago" = "Hace un día"; 54 | 55 | /* No comment provided by engineer. */ 56 | "This morning" = "Esta mañana"; 57 | 58 | /* No comment provided by engineer. */ 59 | "This afternoon" = "Esta tarde"; 60 | 61 | /* No comment provided by engineer. */ 62 | "Today" = "Hoy"; 63 | 64 | /* No comment provided by engineer. */ 65 | "This week" = "Esta semana"; 66 | 67 | /* No comment provided by engineer. */ 68 | "This month" = "Este mes"; 69 | 70 | /* No comment provided by engineer. */ 71 | "This year" = "Este año"; 72 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/lv.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- 1 | /* No comment provided by engineer. */ 2 | "1 year ago" = "Pirms gada"; 3 | 4 | /* No comment provided by engineer. */ 5 | "1 month ago" = "Pirms mēneša"; 6 | 7 | /* No comment provided by engineer. */ 8 | "1 week ago" = "Pirms nedēļas"; 9 | 10 | /* No comment provided by engineer. */ 11 | "1 day ago" = "Pirms dienas"; 12 | 13 | /* No comment provided by engineer. */ 14 | "A minute ago" = "Pirms minūtes"; 15 | 16 | /* No comment provided by engineer. */ 17 | "An hour ago" = "Pirms stundas"; 18 | 19 | /* No comment provided by engineer. */ 20 | "Last month" = "Pagājušajā mēnesī"; 21 | 22 | /* No comment provided by engineer. */ 23 | "Last week" = "Pagājušajā nedēļā"; 24 | 25 | /* No comment provided by engineer. */ 26 | "Last year" = "Pagājušajā gadā"; 27 | 28 | /* No comment provided by engineer. */ 29 | "Just now" = "Tikko"; 30 | 31 | /* No comment provided by engineer. */ 32 | "Today" = "Šodien"; 33 | 34 | /* No comment provided by engineer. */ 35 | "Yesterday" = "Vakar"; 36 | 37 | /* No comment provided by engineer. */ 38 | "This morning" = "Šorīt"; 39 | 40 | /* No comment provided by engineer. */ 41 | "This afternoon" = "Pēcpusdienā"; 42 | 43 | /* No comment provided by engineer. */ 44 | "This week" = "Šonedēļ"; 45 | 46 | /* No comment provided by engineer. */ 47 | "This month" = "Šomēnes"; 48 | 49 | /* No comment provided by engineer. */ 50 | "This year" = "Šogad"; 51 | 52 | /* No comment provided by engineer. */ 53 | "%d seconds ago" = "Pirms %d sekundēm"; 54 | 55 | /* No comment provided by engineer. */ 56 | "%d minutes ago" = "Pirms %d minūtēm"; 57 | 58 | /* No comment provided by engineer. */ 59 | "%d hours ago" = "Pirms %d stundām"; 60 | 61 | /* No comment provided by engineer. */ 62 | "%d days ago" = "Pirms %d dienām"; 63 | 64 | /* No comment provided by engineer. */ 65 | "%d weeks ago" = "Pirms %d nedēļām"; 66 | 67 | /* No comment provided by engineer. */ 68 | "%d months ago" = "Pirms %d mēnešiem"; 69 | 70 | /* No comment provided by engineer. */ 71 | "%d years ago" = "Pirms %d gadiem"; -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/pt-PT.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- 1 | /* No comment provided by engineer. */ 2 | "%d days ago" = "%d dias atrás"; 3 | 4 | /* No comment provided by engineer. */ 5 | "%d hours ago" = "%d horas atrás"; 6 | 7 | /* No comment provided by engineer. */ 8 | "%d minutes ago" = "%d minutos atrás"; 9 | 10 | /* No comment provided by engineer. */ 11 | "%d months ago" = "%d meses atrás"; 12 | 13 | /* No comment provided by engineer. */ 14 | "%d seconds ago" = "%d segundos atrás"; 15 | 16 | /* No comment provided by engineer. */ 17 | "%d weeks ago" = "%d semanas atrás"; 18 | 19 | /* No comment provided by engineer. */ 20 | "%d years ago" = "%d anos atrás"; 21 | 22 | /* No comment provided by engineer. */ 23 | "A minute ago" = "Um minute atrás"; 24 | 25 | /* No comment provided by engineer. */ 26 | "An hour ago" = "Uma hora atrás"; 27 | 28 | /* No comment provided by engineer. */ 29 | "Just now" = "Agora mesmo"; 30 | 31 | /* No comment provided by engineer. */ 32 | "Last month" = "Mês passado"; 33 | 34 | /* No comment provided by engineer. */ 35 | "Last week" = "Semana passada"; 36 | 37 | /* No comment provided by engineer. */ 38 | "Last year" = "Ano passado"; 39 | 40 | /* No comment provided by engineer. */ 41 | "Yesterday" = "Ontem"; 42 | 43 | /* No comment provided by engineer. */ 44 | "1 year ago" = "1 ano passado"; 45 | 46 | /* No comment provided by engineer. */ 47 | "1 month ago" = "1 mês atrás"; 48 | 49 | /* No comment provided by engineer. */ 50 | "1 week ago" = "1 semana atrás"; 51 | 52 | /* No comment provided by engineer. */ 53 | "1 day ago" = "1 dia atrás"; 54 | 55 | /* No comment provided by engineer. */ 56 | "This morning" = "Esta manhã"; 57 | 58 | /* No comment provided by engineer. */ 59 | "This afternoon" = "Esta tarde"; 60 | 61 | /* No comment provided by engineer. */ 62 | "Today" = "Hoje"; 63 | 64 | /* No comment provided by engineer. */ 65 | "This week" = "Esta semana"; 66 | 67 | /* No comment provided by engineer. */ 68 | "This month" = "Este mês"; 69 | 70 | /* No comment provided by engineer. */ 71 | "This year" = "Este ano"; 72 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/de.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- 1 | /* No comment provided by engineer. */ 2 | "%d days ago" = "Vor %d Tagen"; 3 | 4 | /* No comment provided by engineer. */ 5 | "%d hours ago" = "Vor %d Stunden"; 6 | 7 | /* No comment provided by engineer. */ 8 | "%d minutes ago" = "Vor %d Minuten"; 9 | 10 | /* No comment provided by engineer. */ 11 | "%d months ago" = "Vor %d Monaten"; 12 | 13 | /* No comment provided by engineer. */ 14 | "%d seconds ago" = "Vor %d Sekunden"; 15 | 16 | /* No comment provided by engineer. */ 17 | "%d weeks ago" = "Vor %d Wochen"; 18 | 19 | /* No comment provided by engineer. */ 20 | "%d years ago" = "Vor %d Jahren"; 21 | 22 | /* No comment provided by engineer. */ 23 | "A minute ago" = "Vor einer Minute"; 24 | 25 | /* No comment provided by engineer. */ 26 | "An hour ago" = "Vor einer Stunde"; 27 | 28 | /* No comment provided by engineer. */ 29 | "Just now" = "Gerade eben"; 30 | 31 | /* No comment provided by engineer. */ 32 | "Last month" = "Letzten Monat"; 33 | 34 | /* No comment provided by engineer. */ 35 | "Last week" = "Letzte Woche"; 36 | 37 | /* No comment provided by engineer. */ 38 | "Last year" = "Letztes Jahr"; 39 | 40 | /* No comment provided by engineer. */ 41 | "Yesterday" = "Gestern"; 42 | 43 | /* No comment provided by engineer. */ 44 | "1 year ago" = "Vor 1 Jahr"; 45 | 46 | /* No comment provided by engineer. */ 47 | "1 month ago" = "Vor 1 Monat"; 48 | 49 | /* No comment provided by engineer. */ 50 | "1 week ago" = "Vor 1 Woche"; 51 | 52 | /* No comment provided by engineer. */ 53 | "1 day ago" = "Vor 1 Tag"; 54 | 55 | /* No comment provided by engineer. */ 56 | "This morning" = "Heute Morgen"; 57 | 58 | /* No comment provided by engineer. */ 59 | "This afternoon" = "Heute Nachmittag"; 60 | 61 | /* No comment provided by engineer. */ 62 | "Today" = "Heute"; 63 | 64 | /* No comment provided by engineer. */ 65 | "This week" = "Diese Woche"; 66 | 67 | /* No comment provided by engineer. */ 68 | "This month" = "Diesen Monat"; 69 | 70 | /* No comment provided by engineer. */ 71 | "This year" = "Dieses Jahr"; 72 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/sk.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- 1 | /* No comment provided by engineer. */ 2 | "%d days ago" = "Pred %d dňami"; 3 | 4 | /* No comment provided by engineer. */ 5 | "%d hours ago" = "Pred %d hodinami"; 6 | 7 | /* No comment provided by engineer. */ 8 | "%d minutes ago" = "Pred %d minútami"; 9 | 10 | /* No comment provided by engineer. */ 11 | "%d months ago" = "Pred %d mesiaci"; 12 | 13 | /* No comment provided by engineer. */ 14 | "%d seconds ago" = "Pred %d sekundami"; 15 | 16 | /* No comment provided by engineer. */ 17 | "%d weeks ago" = "Pred %d týždňami"; 18 | 19 | /* No comment provided by engineer. */ 20 | "%d years ago" = "Pred %d rokmi"; 21 | 22 | /* No comment provided by engineer. */ 23 | "A minute ago" = "Pred minútou"; 24 | 25 | /* No comment provided by engineer. */ 26 | "An hour ago" = "Pred hodinou"; 27 | 28 | /* No comment provided by engineer. */ 29 | "Just now" = "Práve teraz"; 30 | 31 | /* No comment provided by engineer. */ 32 | "Last month" = "Minulý mesiac"; 33 | 34 | /* No comment provided by engineer. */ 35 | "Last week" = "Minulý týždeň"; 36 | 37 | /* No comment provided by engineer. */ 38 | "Last year" = "Minulý rok"; 39 | 40 | /* No comment provided by engineer. */ 41 | "Yesterday" = "Včera"; 42 | 43 | /* No comment provided by engineer. */ 44 | "1 year ago" = "Pred rokom"; 45 | 46 | /* No comment provided by engineer. */ 47 | "1 month ago" = "Pred mesiacom"; 48 | 49 | /* No comment provided by engineer. */ 50 | "1 week ago" = "Pred týždňom"; 51 | 52 | /* No comment provided by engineer. */ 53 | "1 day ago" = "Predvčerom"; 54 | 55 | /* No comment provided by engineer. */ 56 | "This morning" = "Dnes dopoludnia"; 57 | 58 | /* No comment provided by engineer. */ 59 | "This afternoon" = "Dnes popoludní"; 60 | 61 | /* No comment provided by engineer. */ 62 | "Today" = "Dnes"; 63 | 64 | /* No comment provided by engineer. */ 65 | "This week" = "Tento týždeň"; 66 | 67 | /* No comment provided by engineer. */ 68 | "This month" = "Tento mesiac"; 69 | 70 | /* No comment provided by engineer. */ 71 | "This year" = "Tento rok"; 72 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/sq.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- 1 | /* No comment provided by engineer. */ 2 | "%d days ago" = "%d ditë më parë"; 3 | 4 | /* No comment provided by engineer. */ 5 | "%d hours ago" = "%d orë më parë"; 6 | 7 | /* No comment provided by engineer. */ 8 | "%d minutes ago" = "%d minuta më parë"; 9 | 10 | /* No comment provided by engineer. */ 11 | "%d months ago" = "%d muaj më parë"; 12 | 13 | /* No comment provided by engineer. */ 14 | "%d seconds ago" = "%d sekonda më parë"; 15 | 16 | /* No comment provided by engineer. */ 17 | "%d weeks ago" = "%d javë më parë"; 18 | 19 | /* No comment provided by engineer. */ 20 | "%d years ago" = "%d vite më parë"; 21 | 22 | /* No comment provided by engineer. */ 23 | "A minute ago" = "Një minutë më parë"; 24 | 25 | /* No comment provided by engineer. */ 26 | "An hour ago" = "Një orë më parë"; 27 | 28 | /* No comment provided by engineer. */ 29 | "Just now" = "Tani"; 30 | 31 | /* No comment provided by engineer. */ 32 | "Last month" = "Muajin e kaluar"; 33 | 34 | /* No comment provided by engineer. */ 35 | "Last week" = "Javën e kaluar"; 36 | 37 | /* No comment provided by engineer. */ 38 | "Last year" = "Vitin e kaluar"; 39 | 40 | /* No comment provided by engineer. */ 41 | "Yesterday" = "Dje"; 42 | 43 | /* No comment provided by engineer. */ 44 | "1 year ago" = "1 vit më parë"; 45 | 46 | /* No comment provided by engineer. */ 47 | "1 month ago" = "1 muaj më parë"; 48 | 49 | /* No comment provided by engineer. */ 50 | "1 week ago" = "1 javë më parë"; 51 | 52 | /* No comment provided by engineer. */ 53 | "1 day ago" = "1 ditë më parë"; 54 | 55 | /* No comment provided by engineer. */ 56 | "This morning" = "Këtë mëngjes"; 57 | 58 | /* No comment provided by engineer. */ 59 | "This afternoon" = "Këtë pasdite"; 60 | 61 | /* No comment provided by engineer. */ 62 | "Today" = "Sot"; 63 | 64 | /* No comment provided by engineer. */ 65 | "This week" = "Këtë javë"; 66 | 67 | /* No comment provided by engineer. */ 68 | "This month" = "Këtë muaj"; 69 | 70 | /* No comment provided by engineer. */ 71 | "This year" = "Këtë vit"; -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/nl.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- 1 | /* No comment provided by engineer. */ 2 | "%d days ago" = "%d dagen geleden"; 3 | 4 | /* No comment provided by engineer. */ 5 | "%d hours ago" = "%d uur geleden"; 6 | 7 | /* No comment provided by engineer. */ 8 | "%d minutes ago" = "%d minuten geleden"; 9 | 10 | /* No comment provided by engineer. */ 11 | "%d months ago" = "%d maanden geleden"; 12 | 13 | /* No comment provided by engineer. */ 14 | "%d seconds ago" = "%d seconden geleden"; 15 | 16 | /* No comment provided by engineer. */ 17 | "%d weeks ago" = "%d weken geleden"; 18 | 19 | /* No comment provided by engineer. */ 20 | "%d years ago" = "%d jaar geleden"; 21 | 22 | /* No comment provided by engineer. */ 23 | "A minute ago" = "Een minuut geleden"; 24 | 25 | /* No comment provided by engineer. */ 26 | "An hour ago" = "Een uur geleden"; 27 | 28 | /* No comment provided by engineer. */ 29 | "Just now" = "Zojuist"; 30 | 31 | /* No comment provided by engineer. */ 32 | "Last month" = "Vorige maand"; 33 | 34 | /* No comment provided by engineer. */ 35 | "Last week" = "Vorige week"; 36 | 37 | /* No comment provided by engineer. */ 38 | "Last year" = "Vorig jaar"; 39 | 40 | /* No comment provided by engineer. */ 41 | "Yesterday" = "Gisteren"; 42 | 43 | /* No comment provided by engineer. */ 44 | "1 year ago" = "1 jaar geleden"; 45 | 46 | /* No comment provided by engineer. */ 47 | "1 month ago" = "1 maand geleden"; 48 | 49 | /* No comment provided by engineer. */ 50 | "1 week ago" = "1 week geleden"; 51 | 52 | /* No comment provided by engineer. */ 53 | "1 day ago" = "1 dag geleden"; 54 | 55 | /* No comment provided by engineer. */ 56 | "This morning" = "Vanmorgen"; 57 | 58 | /* No comment provided by engineer. */ 59 | "This afternoon" = "Vanmiddag"; 60 | 61 | /* No comment provided by engineer. */ 62 | "Today" = "Vandaag"; 63 | 64 | /* No comment provided by engineer. */ 65 | "This week" = "Deze week"; 66 | 67 | /* No comment provided by engineer. */ 68 | "This month" = "Deze maand"; 69 | 70 | /* No comment provided by engineer. */ 71 | "This year" = "Dit jaar"; 72 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/bg.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- 1 | /* No comment provided by engineer. */ 2 | "%d days ago" = "преди %d дена"; 3 | 4 | /* No comment provided by engineer. */ 5 | "%d hours ago" = "преди %d часа"; 6 | 7 | /* No comment provided by engineer. */ 8 | "%d minutes ago" = "преди %d минути"; 9 | 10 | /* No comment provided by engineer. */ 11 | "%d months ago" = "преди %d месеца"; 12 | 13 | /* No comment provided by engineer. */ 14 | "%d seconds ago" = "преди %d секунди"; 15 | 16 | /* No comment provided by engineer. */ 17 | "%d weeks ago" = "преди %d седмици"; 18 | 19 | /* No comment provided by engineer. */ 20 | "%d years ago" = "преди %d години"; 21 | 22 | /* No comment provided by engineer. */ 23 | "A minute ago" = "преди минута"; 24 | 25 | /* No comment provided by engineer. */ 26 | "An hour ago" = "преди час"; 27 | 28 | /* No comment provided by engineer. */ 29 | "Just now" = "току що"; 30 | 31 | /* No comment provided by engineer. */ 32 | "Last month" = "през последния месец"; 33 | 34 | /* No comment provided by engineer. */ 35 | "Last week" = "през последната седмица"; 36 | 37 | /* No comment provided by engineer. */ 38 | "Last year" = "през последната година"; 39 | 40 | /* No comment provided by engineer. */ 41 | "Yesterday" = "вчера"; 42 | 43 | /* No comment provided by engineer. */ 44 | "1 year ago" = "преди 1 година"; 45 | 46 | /* No comment provided by engineer. */ 47 | "1 month ago" = "преди 1 месец"; 48 | 49 | /* No comment provided by engineer. */ 50 | "1 week ago" = "преди 1 седмица"; 51 | 52 | /* No comment provided by engineer. */ 53 | "1 day ago" = "преди 1 ден"; 54 | 55 | /* No comment provided by engineer. */ 56 | "This morning" = "тази сутрин"; 57 | 58 | /* No comment provided by engineer. */ 59 | "This afternoon" = "тази вечер"; 60 | 61 | /* No comment provided by engineer. */ 62 | "Today" = "днес"; 63 | 64 | /* No comment provided by engineer. */ 65 | "This week" = "тази седмица"; 66 | 67 | /* No comment provided by engineer. */ 68 | "This month" = "този месец"; 69 | 70 | /* No comment provided by engineer. */ 71 | "This year" = "тази година"; 72 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/is.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- 1 | /* No comment provided by engineer. */ 2 | "%d days ago" = "%d dögum síðan"; 3 | 4 | /* No comment provided by engineer. */ 5 | "%d hours ago" = "%d klst. síðan"; 6 | 7 | /* No comment provided by engineer. */ 8 | "%d minutes ago" = "%d mínútum síðan"; 9 | 10 | /* No comment provided by engineer. */ 11 | "%d months ago" = "%d mánuðum síðan"; 12 | 13 | /* No comment provided by engineer. */ 14 | "%d seconds ago" = "%d sekúndum síðan"; 15 | 16 | /* No comment provided by engineer. */ 17 | "%d weeks ago" = "%d vikum síðan"; 18 | 19 | /* No comment provided by engineer. */ 20 | "%d years ago" = "%d árum síðan"; 21 | 22 | /* No comment provided by engineer. */ 23 | "A minute ago" = "Einni mínútu síðan"; 24 | 25 | /* No comment provided by engineer. */ 26 | "An hour ago" = "Einni klst. síðan"; 27 | 28 | /* No comment provided by engineer. */ 29 | "Just now" = "Rétt í þessu"; 30 | 31 | /* No comment provided by engineer. */ 32 | "Last month" = "Í síðasta mánuði"; 33 | 34 | /* No comment provided by engineer. */ 35 | "Last week" = "Í síðustu viku"; 36 | 37 | /* No comment provided by engineer. */ 38 | "Last year" = "Á síðasta ári"; 39 | 40 | /* No comment provided by engineer. */ 41 | "Yesterday" = "Í gær"; 42 | 43 | /* No comment provided by engineer. */ 44 | "1 year ago" = "1 ári síðan"; 45 | 46 | /* No comment provided by engineer. */ 47 | "1 month ago" = "1 mánuði síðan"; 48 | 49 | /* No comment provided by engineer. */ 50 | "1 week ago" = "1 viku síðan"; 51 | 52 | /* No comment provided by engineer. */ 53 | "1 day ago" = "1 degi síðan"; 54 | 55 | /* No comment provided by engineer. */ 56 | "This morning" = "Í morgun"; 57 | 58 | /* No comment provided by engineer. */ 59 | "This afternoon" = "Síðdegis"; 60 | 61 | /* No comment provided by engineer. */ 62 | "Today" = "Í dag"; 63 | 64 | /* No comment provided by engineer. */ 65 | "This week" = "Í þessari viku"; 66 | 67 | /* No comment provided by engineer. */ 68 | "This month" = "Í þessum mánuði"; 69 | 70 | /* No comment provided by engineer. */ 71 | "This year" = "Á þessu ári"; 72 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributor Guidelines 2 | 3 | So you want to help us making a better SwiftMoment? Thanks! For the sake 4 | of a productive collaboration, please pay attention to the following 5 | collaboration guidelines: 6 | 7 | ## Pull Requests > Issues 8 | 9 | Whenever possible, try to provide us with [pull 10 | requests](https://help.github.com/articles/creating-a-pull-request/) 11 | instead of simply creating an issue. Pull requests help us move forward 12 | faster, and we will be glad to review and eventually include it in the 13 | master branch. 14 | 15 | ## Issues 16 | 17 | If you open an issue, make sure to include a complete description. 18 | Follow the template that appears on the form, including as much 19 | information as possible. You should include code snippets that helps us 20 | reproduce the error. Saying "it does not work" without further context 21 | does not help anybody. 22 | 23 | ## Pull Requests 24 | 25 | If you create a pull request, please be aware that we only accept pull 26 | requests that include unit tests for your changes. **We do not accept 27 | pull requests without the appropriate unit tests** unless they are just 28 | grammar, cosmetic, documentation or typographical corrections. 29 | 30 | Before sending a pull request, make sure that: 31 | 32 | 1. Your code compiles without warnings of any kind. 33 | 2. Your code runs without runtime warnings. 34 | 3. You have checked your code with either 35 | [SwiftLint](https://github.com/realm/SwiftLint) or 36 | [Tailor](https://tailor.sh) and you have removed any warnings shown 37 | by either of these tools. 38 | 4. You have included unit tests for your feature, if required. 39 | 5. All previous unit tests pass. 40 | 6. You have included and/or updated API documentation in the public 41 | methods, structs and classes that are referenced by your pull 42 | request. 43 | 44 | ## Behaviour 45 | 46 | We want SwiftMoment to be an inclusive project. Please be kind and 47 | helpful in your comments. In case of doubt, ask questions. Be honest and 48 | humble. May SwiftMoment be a better place after you have been here :) 49 | 50 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/pl.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- 1 | /* No comment provided by engineer. */ 2 | "%d days ago" = "%d dni temu"; 3 | 4 | /* No comment provided by engineer. */ 5 | "%d hours ago" = "%d godzin(y) temu"; 6 | 7 | /* No comment provided by engineer. */ 8 | "%d minutes ago" = "%d minut(y) temu"; 9 | 10 | /* No comment provided by engineer. */ 11 | "%d months ago" = "%d miesiące/-y temu"; 12 | 13 | /* No comment provided by engineer. */ 14 | "%d seconds ago" = "%d sekund(y) temu"; 15 | 16 | /* No comment provided by engineer. */ 17 | "%d weeks ago" = "%d tygodni(e) temu"; 18 | 19 | /* No comment provided by engineer. */ 20 | "%d years ago" = "%d lat(a) temu"; 21 | 22 | /* No comment provided by engineer. */ 23 | "A minute ago" = "Minutę temu"; 24 | 25 | /* No comment provided by engineer. */ 26 | "An hour ago" = "Godzinę temu"; 27 | 28 | /* No comment provided by engineer. */ 29 | "Just now" = "W tej chwili"; 30 | 31 | /* No comment provided by engineer. */ 32 | "Last month" = "W zeszłym miesiącu"; 33 | 34 | /* No comment provided by engineer. */ 35 | "Last week" = "W zeszłym tygodniu"; 36 | 37 | /* No comment provided by engineer. */ 38 | "Last year" = "W zeszłym roku"; 39 | 40 | /* No comment provided by engineer. */ 41 | "Yesterday" = "Wczoraj"; 42 | 43 | /* No comment provided by engineer. */ 44 | "1 year ago" = "1 rok temu"; 45 | 46 | /* No comment provided by engineer. */ 47 | "1 month ago" = "1 miesiąc temu"; 48 | 49 | /* No comment provided by engineer. */ 50 | "1 week ago" = "1 tydzień temu"; 51 | 52 | /* No comment provided by engineer. */ 53 | "1 day ago" = "1 dzień temu"; 54 | 55 | /* No comment provided by engineer. */ 56 | "This morning" = "Dziś rano"; 57 | 58 | /* No comment provided by engineer. */ 59 | "This afternoon" = "Dziś po południu"; 60 | 61 | /* No comment provided by engineer. */ 62 | "Today" = "Dzisiaj"; 63 | 64 | /* No comment provided by engineer. */ 65 | "This week" = "W tym tygodniu"; 66 | 67 | /* No comment provided by engineer. */ 68 | "This month" = "W tym miesiącu"; 69 | 70 | /* No comment provided by engineer. */ 71 | "This year" = "W tym roku"; 72 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/fi.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- 1 | /* No comment provided by engineer. */ 2 | "%d days ago" = "%d päivää sitten"; 3 | 4 | /* No comment provided by engineer. */ 5 | "%d hours ago" = "%d tuntia sitten"; 6 | 7 | /* No comment provided by engineer. */ 8 | "%d minutes ago" = "%d minuuttia sitten"; 9 | 10 | /* No comment provided by engineer. */ 11 | "%d months ago" = "%d kuukautta sitten"; 12 | 13 | /* No comment provided by engineer. */ 14 | "%d seconds ago" = "%d sekuntia sitten"; 15 | 16 | /* No comment provided by engineer. */ 17 | "%d weeks ago" = "%d viikkoa sitten"; 18 | 19 | /* No comment provided by engineer. */ 20 | "%d years ago" = "%d vuotta sitten"; 21 | 22 | /* No comment provided by engineer. */ 23 | "A minute ago" = "Minuutti sitten"; 24 | 25 | /* No comment provided by engineer. */ 26 | "An hour ago" = "Tunti sitten"; 27 | 28 | /* No comment provided by engineer. */ 29 | "Just now" = "Juuri äsken"; 30 | 31 | /* No comment provided by engineer. */ 32 | "Last month" = "Viime kuussa"; 33 | 34 | /* No comment provided by engineer. */ 35 | "Last week" = "Viime viikolla"; 36 | 37 | /* No comment provided by engineer. */ 38 | "Last year" = "Viime vuonna"; 39 | 40 | /* No comment provided by engineer. */ 41 | "Yesterday" = "Eilen"; 42 | 43 | /* No comment provided by engineer. */ 44 | "1 year ago" = "Vuosi sitten"; 45 | 46 | /* No comment provided by engineer. */ 47 | "1 month ago" = "Kuukausi sitten"; 48 | 49 | /* No comment provided by engineer. */ 50 | "1 week ago" = "Viikko sitten"; 51 | 52 | /* No comment provided by engineer. */ 53 | "1 day ago" = "Vuorokausi sitten"; 54 | 55 | /* No comment provided by engineer. */ 56 | "This morning" = "Tänä aamuna"; 57 | 58 | /* No comment provided by engineer. */ 59 | "This afternoon" = "Tänä iltapäivänä"; 60 | 61 | /* No comment provided by engineer. */ 62 | "Today" = "Tänään"; 63 | 64 | /* No comment provided by engineer. */ 65 | "This week" = "Tällä viikolla"; 66 | 67 | /* No comment provided by engineer. */ 68 | "This month" = "Tässä kuussa"; 69 | 70 | /* No comment provided by engineer. */ 71 | "This year" = "Tänä vuonna"; 72 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/fr.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- 1 | /* No comment provided by engineer. */ 2 | "%d days ago" = "Il y a %d jours"; 3 | 4 | /* No comment provided by engineer. */ 5 | "%d hours ago" = "Il y a %d heures"; 6 | 7 | /* No comment provided by engineer. */ 8 | "%d minutes ago" = "Il y a %d minutes"; 9 | 10 | /* No comment provided by engineer. */ 11 | "%d months ago" = "Il y a %d mois"; 12 | 13 | /* No comment provided by engineer. */ 14 | "%d seconds ago" = "Il y a %d secondes"; 15 | 16 | /* No comment provided by engineer. */ 17 | "%d weeks ago" = "Il y a %d semaines"; 18 | 19 | /* No comment provided by engineer. */ 20 | "%d years ago" = "Il y a %d ans"; 21 | 22 | /* No comment provided by engineer. */ 23 | "A minute ago" = "Il y a une minute"; 24 | 25 | /* No comment provided by engineer. */ 26 | "An hour ago" = "Il y a une heure"; 27 | 28 | /* No comment provided by engineer. */ 29 | "Just now" = "A l'instant"; 30 | 31 | /* No comment provided by engineer. */ 32 | "Last month" = "Le mois dernier"; 33 | 34 | /* No comment provided by engineer. */ 35 | "Last week" = "La semaine dernière"; 36 | 37 | /* No comment provided by engineer. */ 38 | "Last year" = "L'année dernière"; 39 | 40 | /* No comment provided by engineer. */ 41 | "Yesterday" = "Hier"; 42 | 43 | /* No comment provided by engineer. */ 44 | "1 year ago" = "Il y a 1 an"; 45 | 46 | /* No comment provided by engineer. */ 47 | "1 month ago" = "Il y a 1 mois"; 48 | 49 | /* No comment provided by engineer. */ 50 | "1 week ago" = "Il y a 1 semaine"; 51 | 52 | /* No comment provided by engineer. */ 53 | "1 day ago" = "Il y a 1 jour"; 54 | 55 | /* No comment provided by engineer. */ 56 | "This morning" = "Ce matin"; 57 | 58 | /* No comment provided by engineer. */ 59 | "This afternoon" = "Cet après-midi"; 60 | 61 | /* No comment provided by engineer. */ 62 | "Today" = "Aujourd'hui"; 63 | 64 | /* No comment provided by engineer. */ 65 | "This week" = "Cette semaine"; 66 | 67 | /* No comment provided by engineer. */ 68 | "This month" = "Ce mois-ci"; 69 | 70 | /* No comment provided by engineer. */ 71 | "This year" = "Cette année"; 72 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/ms.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- 1 | /* No comment provided by engineer. */ 2 | "%d days ago" = "%d hari yang lalu"; 3 | 4 | /* No comment provided by engineer. */ 5 | "%d hours ago" = "%d jam yang lalu"; 6 | 7 | /* No comment provided by engineer. */ 8 | "%d minutes ago" = "%d minit yang lalu"; 9 | 10 | /* No comment provided by engineer. */ 11 | "%d months ago" = "%d bulan yang lalu"; 12 | 13 | /* No comment provided by engineer. */ 14 | "%d seconds ago" = "%d saat yang lalu"; 15 | 16 | /* No comment provided by engineer. */ 17 | "%d weeks ago" = "%d minggu yang lalu"; 18 | 19 | /* No comment provided by engineer. */ 20 | "%d years ago" = "%d tahun yang lalu"; 21 | 22 | /* No comment provided by engineer. */ 23 | "A minute ago" = "Seminit yang lalu"; 24 | 25 | /* No comment provided by engineer. */ 26 | "An hour ago" = "Sejam yang lalu"; 27 | 28 | /* No comment provided by engineer. */ 29 | "Just now" = "Sebentar tadi"; 30 | 31 | /* No comment provided by engineer. */ 32 | "Last month" = "Sebulan yang lalu"; 33 | 34 | /* No comment provided by engineer. */ 35 | "Last week" = "Seminggu yang lalu"; 36 | 37 | /* No comment provided by engineer. */ 38 | "Last year" = "Setahun yang lalu"; 39 | 40 | /* No comment provided by engineer. */ 41 | "Yesterday" = "Semalam"; 42 | 43 | /* No comment provided by engineer. */ 44 | "1 year ago" = "Setahun yang lalu"; 45 | 46 | /* No comment provided by engineer. */ 47 | "1 month ago" = "Sebulan yang lali"; 48 | 49 | /* No comment provided by engineer. */ 50 | "1 week ago" = "Seminggu yang lalu"; 51 | 52 | /* No comment provided by engineer. */ 53 | "1 day ago" = "Semalam"; 54 | 55 | /* No comment provided by engineer. */ 56 | "This morning" = "Pagi ini"; 57 | 58 | /* No comment provided by engineer. */ 59 | "This afternoon" = "Tengahari ini"; 60 | 61 | /* No comment provided by engineer. */ 62 | "Today" = "Hari ini"; 63 | 64 | /* No comment provided by engineer. */ 65 | "This week" = "Minggu ini"; 66 | 67 | /* No comment provided by engineer. */ 68 | "This month" = "Bulan ini"; 69 | 70 | /* No comment provided by engineer. */ 71 | "This year" = "Tahun ini"; -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/ro.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- 1 | /* No comment provided by engineer. */ 2 | "%d days ago" = "În urmă cu %d zile"; 3 | 4 | /* No comment provided by engineer. */ 5 | "%d hours ago" = "În urmă cu %d ore"; 6 | 7 | /* No comment provided by engineer. */ 8 | "%d minutes ago" = "În urmă cu %d minute"; 9 | 10 | /* No comment provided by engineer. */ 11 | "%d months ago" = "În urmă cu %d luni"; 12 | 13 | /* No comment provided by engineer. */ 14 | "%d seconds ago" = "În urmă cu %d secunde"; 15 | 16 | /* No comment provided by engineer. */ 17 | "%d weeks ago" = "În urmă cu %d săptămâni"; 18 | 19 | /* No comment provided by engineer. */ 20 | "%d years ago" = "În urmă cu %d ani"; 21 | 22 | /* No comment provided by engineer. */ 23 | "A minute ago" = "În urmă cu 1 minut"; 24 | 25 | /* No comment provided by engineer. */ 26 | "An hour ago" = "În urmă cu 1 oră"; 27 | 28 | /* No comment provided by engineer. */ 29 | "Just now" = "Acum câteva momente"; 30 | 31 | /* No comment provided by engineer. */ 32 | "Last month" = "Luna trecută"; 33 | 34 | /* No comment provided by engineer. */ 35 | "Last week" = "Săptămâna trecută"; 36 | 37 | /* No comment provided by engineer. */ 38 | "Last year" = "Anul trecut"; 39 | 40 | /* No comment provided by engineer. */ 41 | "Yesterday" = "Ieri"; 42 | 43 | /* No comment provided by engineer. */ 44 | "1 year ago" = "În urmă cu 1 an"; 45 | 46 | /* No comment provided by engineer. */ 47 | "1 month ago" = "În urmă cu 1 lună"; 48 | 49 | /* No comment provided by engineer. */ 50 | "1 week ago" = "În urmă cu 1 săptămână"; 51 | 52 | /* No comment provided by engineer. */ 53 | "1 day ago" = "În urmă cu 1 zi"; 54 | 55 | /* No comment provided by engineer. */ 56 | "This morning" = "Azi dimineață"; 57 | 58 | /* No comment provided by engineer. */ 59 | "This afternoon" = "În această seară"; 60 | 61 | /* No comment provided by engineer. */ 62 | "Today" = "Astăzi"; 63 | 64 | /* No comment provided by engineer. */ 65 | "This week" = "Săptămâna aceasta"; 66 | 67 | /* No comment provided by engineer. */ 68 | "This month" = "Luna aceasta"; 69 | 70 | /* No comment provided by engineer. */ 71 | "This year" = "Anul acesta"; -------------------------------------------------------------------------------- /CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | Contributors 2 | ============ 3 | 4 | This is the list of people that have helped making SwiftMoment with pull 5 | requests, bug submissions, etc: 6 | 7 | - [박현재](https://github.com/hyeonjae) 8 | - [akihiro0228](https://github.com/akihiro0228) 9 | - [Aaron Brager](https://github.com/getaaron) 10 | - [Adriano Goncalves](https://github.com/amg1976) 11 | - [Anders Klenke](https://github.com/andersklenke) 12 | - [Andrew Barba](https://github.com/AndrewBarba) 13 | - [Andrew Branch](https://github.com/andrewbranch) 14 | - [Burak Akkaş](https://github.com/javasch) 15 | - [Chris Sloey](https://github.com/chrissloey) 16 | - [Daniel Cestari](https://github.com/dcestari) 17 | - [David Harris](https://github.com/toadzky) 18 | - [Eric Fang](https://github.com/fjhixiuxiu) 19 | - [Fabio Felici](https://github.com/fabfelici) 20 | - [Florent Pillet](https://github.com/fpillet) 21 | - [Hadar Landao](https://github.com/hlandao) 22 | - [Jake Johnson](https://github.com/johnsonjake) 23 | - [karupanenura](https://github.com/karupanerura) 24 | - [Ken Goldfarb](https://github.com/kengoldfarb) 25 | - [Laurin Brandner](https://github.com/larcus94) 26 | - [Madhava Jay](https://github.com/madhavajay) 27 | - [Masaya Yashiro](https://github.com/yashims) 28 | - [Mihyaeru](https://github.com/mihyaeru21) 29 | - [Narayan Sainaney](https://github.com/nsainaney) 30 | - [Nate Armstrong](https://github.com/n8armstrong) 31 | - [Neil](https://github.com/AsFarA) 32 | - [PG Herveou](https://github.com/pgherveou) 33 | - [Pine Mizune](https://github.com/pine613) 34 | - [Robert La Ferla](https://github.com/rlaferla) 35 | - [Ryan Maxwell](https://github.com/ryanmaxwell) 36 | - [Ryo Yamada](https://github.com/Liooo) 37 | - [Tatiana Magdalena](https://github.com/tatimagdalena) 38 | - [Tomáš Slíž](https://github.com/tomassliz) 39 | 40 | Special Thanks 41 | -------------- 42 | 43 | A big shoutout to [Dave Verwer](https://twitter.com/daveverwer) who 44 | kindly featured SwiftMoment in [iOS Dev Weekly issue 45 | 186](http://iosdevweekly.com/issues/186), to [Natasha 46 | Murashev](http://natashatherobot.com) who also featured SwiftMoment in 47 | her newsletter, and to [Swift Sandbox](http://swiftsandbox.io) who 48 | featured SwiftMoment in [issue 36](http://swiftsandbox.io/issues/36?#start)! 49 | Please make sure to subscribe to all of these newsletters! 50 | 51 | Also thanks to [Matteo Crippa](https://github.com/matteocrippa) and 52 | [dkhamsing](https://github.com/dkhamsing) for featuring SwiftMoment in 53 | the [awesome swift](https://github.com/matteocrippa/awesome-swift) list! 54 | 55 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMomentTests/DurationTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DurationTests.swift 3 | // SwiftMoment 4 | // 5 | // Created by Adrian on 19/01/15. 6 | // Copyright (c) 2015 Adrian Kosmaczewski. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import XCTest 11 | import SwiftMoment 12 | 13 | class DurationTests: XCTestCase { 14 | 15 | override func setUp() { 16 | super.setUp() 17 | } 18 | 19 | override func tearDown() { 20 | super.tearDown() 21 | } 22 | 23 | func testCanCreateDurationsFromIntegers() { 24 | let duration = Duration(value: 10000000) 25 | let durationString = "The Duration instance wraps an NSTimeInterval in seconds" 26 | XCTAssertEqual(duration.seconds, 10000000, durationString) 27 | } 28 | 29 | func testCanCreateDurationsFromDoubles() { 30 | let duration = Duration(value: 10000000.1000) 31 | let durationString = "The Duration instance wraps an NSTimeInterval in seconds" 32 | XCTAssertEqual(duration.seconds, 10000000.1000, durationString) 33 | } 34 | 35 | func testCanGenerateMomentAgo() { 36 | let date = 2.months.ago() 37 | XCTAssert(date ~= (moment() - 2.months), "'ago()' returns a moment in the past") 38 | } 39 | 40 | func testSinceReturnsDuration() { 41 | let date = 2.months.ago() + 3.hours + 5.minutes 42 | let duration = since(date) 43 | let seconds = Int(duration.seconds) 44 | XCTAssertEqual(seconds, 5172900, "That date happened 5172900 seconds ago") 45 | } 46 | 47 | func testCanAddAndSubstractDurations() { 48 | let birthday = moment("09/04/1973")! 49 | let duration = Duration(value: 107567580) 50 | let subtracted = birthday - (3.years + 5.months - 7.minutes) 51 | let subtracted2 = birthday - duration 52 | XCTAssertEqual(subtracted, subtracted2, "Both operations yield the same result") 53 | } 54 | 55 | func testDurationDescription() { 56 | let duration = 4.months + 53.days + 6.hours + 4.minutes 57 | let str = duration.description 58 | let durationString = "The description of a duration provides quite a bit of info" 59 | XCTAssertEqual(str, "5mo 3w 1d 6:04:00", durationString) 60 | } 61 | 62 | func testDurationProperties() { 63 | let duration = 4.months + 53.days + 6.hours + 4.minutes 64 | let quarters = duration.quarters 65 | let months = duration.months 66 | let hours = duration.hours 67 | let minutes = duration.minutes 68 | let days = duration.days 69 | XCTAssertEqual(round(quarters), 2) 70 | XCTAssertEqual(round(months), 6) 71 | XCTAssertEqual(round(hours), 4158) 72 | XCTAssertEqual(minutes, 249484) 73 | XCTAssertEqual(round(days), 173) 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Extensions.swift 3 | // SwiftMoment 4 | // 5 | // Created by Adrian on 19/01/15. 6 | // Copyright (c) 2015 Adrian Kosmaczewski. All rights reserved. 7 | // 8 | 9 | public extension Int { 10 | 11 | /// Creates a duration value with the current number of seconds. 12 | var seconds: Duration { 13 | return Duration(value: self) 14 | } 15 | 16 | /// Creates a duration value with the current number of minutes. 17 | var minutes: Duration { 18 | return Duration(value: self * Int(Moment.minuteInSeconds)) 19 | } 20 | 21 | /// Creates a duration value with the current number of hours. 22 | var hours: Duration { 23 | return Duration(value: self * Int(Moment.hourInSeconds)) 24 | } 25 | 26 | /// Creates a duration value with the current number of weeks. 27 | var weeks: Duration { 28 | return Duration(value: self * Int(Moment.weekInSeconds)) 29 | } 30 | 31 | /// Creates a duration value with the current number of days. 32 | var days: Duration { 33 | return Duration(value: self * Int(Moment.dayInSeconds)) 34 | } 35 | 36 | /// Creates a duration value with the current number of months. 37 | var months: Duration { 38 | return Duration(value: self * Int(Moment.monthInSeconds)) 39 | } 40 | 41 | /// Creates a duration value with the current number of quarters. 42 | var quarters: Duration { 43 | return Duration(value: self * Int(Moment.quarterInSeconds)) 44 | } 45 | 46 | /// Creates a duration value with the current number of years. 47 | var years: Duration { 48 | return Duration(value: self * Int(Moment.yearInSeconds)) 49 | } 50 | } 51 | 52 | public extension Double { 53 | 54 | /// Creates a duration value with the current number of seconds. 55 | var seconds: Duration { 56 | return Duration(value: self) 57 | } 58 | 59 | /// Creates a duration value with the current number of minutes. 60 | var minutes: Duration { 61 | return Duration(value: self * Moment.minuteInSeconds) 62 | } 63 | 64 | /// Creates a duration value with the current number of hours. 65 | var hours: Duration { 66 | return Duration(value: self * Moment.hourInSeconds) 67 | } 68 | 69 | /// Creates a duration value with the current number of weeks. 70 | var weeks: Duration { 71 | return Duration(value: self * Moment.weekInSeconds) 72 | } 73 | 74 | /// Creates a duration value with the current number of days. 75 | var days: Duration { 76 | return Duration(value: self * Moment.dayInSeconds) 77 | } 78 | 79 | /// Creates a duration value with the current number of months. 80 | var months: Duration { 81 | return Duration(value: self * Moment.monthInSeconds) 82 | } 83 | 84 | /// Creates a duration value with the current number of quarters. 85 | var quarters: Duration { 86 | return Duration(value: self * Moment.quarterInSeconds) 87 | } 88 | 89 | /// Creates a duration value with the current number of years. 90 | var years: Duration { 91 | return Duration(value: self * Moment.yearInSeconds) 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment.xcodeproj/xcshareddata/xcschemes/SwiftMoment watchOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 32 | 33 | 34 | 35 | 36 | 37 | 48 | 49 | 55 | 56 | 57 | 58 | 59 | 60 | 66 | 67 | 73 | 74 | 75 | 76 | 78 | 79 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/nb.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- 1 | /* 2 | RULES: 3 | Assume value for (seconds, hours, minutes, days, weeks, months or years) is XXXY, Y is last digit, XY is last two digits; 4 | */ 5 | 6 | /* Y ==0 OR Y > 4 OR XY == 11; */ 7 | "%d days ago" = "%d dager siden"; 8 | 9 | /* If Y != 1 AND Y < 5; */ 10 | "%d _days ago" = "%d dager siden"; 11 | 12 | /* If Y == 1; */ 13 | "%d __days ago" = "%d dag siden"; 14 | 15 | 16 | /* Y ==0 OR Y > 4 OR XY == 11; */ 17 | "%d hours ago" = "%d timer siden"; 18 | 19 | /* If Y != 1 AND Y < 5; */ 20 | "%d _hours ago" = "%d timer siden"; 21 | 22 | /* If Y == 1; */ 23 | "%d __hours ago" = "%d time siden"; 24 | 25 | 26 | /* Y ==0 OR Y > 4 OR XY == 11; */ 27 | "%d minutes ago" = "%d minutter siden"; 28 | 29 | /* If Y != 1 AND Y < 5; */ 30 | "%d _minutes ago" = "%d minutter siden"; 31 | 32 | /* If Y == 1; */ 33 | "%d __minutes ago" = "%d minutt siden"; 34 | 35 | 36 | /* Y ==0 OR Y > 4 OR XY == 11; */ 37 | "%d months ago" = "%d måneder siden"; 38 | 39 | /* If Y != 1 AND Y < 5; */ 40 | "%d _months ago" = "%d måneder siden"; 41 | 42 | /* If Y == 1; */ 43 | "%d __months ago" = "%d måned siden"; 44 | 45 | 46 | /* Y ==0 OR Y > 4 OR XY == 11; */ 47 | "%d seconds ago" = "%d sekunder siden"; 48 | 49 | /* If Y != 1 AND Y < 5; */ 50 | "%d _seconds ago" = "%d sekunder siden"; 51 | 52 | /* If Y == 1; */ 53 | "%d __seconds ago" = "%d sekund siden"; 54 | 55 | 56 | /* Y ==0 OR Y > 4 OR XY == 11; */ 57 | "%d weeks ago" = "%d uker siden"; 58 | 59 | /* If Y != 1 AND Y < 5; */ 60 | "%d _weeks ago" = "%d uker siden"; 61 | 62 | /* If Y == 1; */ 63 | "%d __weeks ago" = "%d uke siden"; 64 | 65 | 66 | /* Y ==0 OR Y > 4 OR XY == 11; */ 67 | "%d years ago" = "%d år siden"; 68 | 69 | /* If Y != 1 AND Y < 5; */ 70 | "%d _years ago" = "%d år siden"; 71 | 72 | /* If Y == 1; */ 73 | "%d __years ago" = "%d år siden"; 74 | 75 | 76 | /* No comment provided by engineer. */ 77 | "A minute ago" = "Et minutt siden"; 78 | 79 | /* No comment provided by engineer. */ 80 | "An hour ago" = "Én time siden"; 81 | 82 | /* No comment provided by engineer. */ 83 | "Just now" = "Nå"; 84 | 85 | /* No comment provided by engineer. */ 86 | "Last month" = "For en måned siden"; 87 | 88 | /* No comment provided by engineer. */ 89 | "Last week" = "For en uke siden"; 90 | 91 | /* No comment provided by engineer. */ 92 | "Last year" = "For et år siden"; 93 | 94 | /* No comment provided by engineer. */ 95 | "Yesterday" = "I går"; 96 | 97 | /* No comment provided by engineer. */ 98 | "1 year ago" = "1 år siden"; 99 | 100 | /* No comment provided by engineer. */ 101 | "1 month ago" = "1 måned siden"; 102 | 103 | /* No comment provided by engineer. */ 104 | "1 week ago" = "1 uke siden"; 105 | 106 | /* No comment provided by engineer. */ 107 | "1 day ago" = "1 dag siden"; 108 | 109 | /* No comment provided by engineer. */ 110 | "This morning" = "Denne morgenen"; 111 | 112 | /* No comment provided by engineer. */ 113 | "This afternoon" = "I ettermiddag"; 114 | 115 | /* No comment provided by engineer. */ 116 | "Today" = "I dag"; 117 | 118 | /* No comment provided by engineer. */ 119 | "This week" = "Denne uken"; 120 | 121 | /* No comment provided by engineer. */ 122 | "This month" = "Denne måneden"; 123 | 124 | /* No comment provided by engineer. */ 125 | "This year" = "Dette året"; 126 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/uk.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- 1 | /* 2 | RULES: 3 | Assume value for (seconds, hours, minutes, days, weeks, months or years) is XXXY, Y is last digit, XY is last two digits; 4 | */ 5 | 6 | /* Y == 0 OR Y > 4 OR (XY > 10 AND XY < 15); */ 7 | "%d days ago" = "%d днів тому"; 8 | 9 | /* Y > 1 AND Y < 5 AND (XY < 10 OR XY > 20); */ 10 | "%d _days ago" = "%d дня тому"; 11 | 12 | /* Y == 1 AND XY != 11; */ 13 | "%d __days ago" = "%d день тому"; 14 | 15 | 16 | /* Y == 0 OR Y > 4 OR (XY > 10 AND XY < 15); */ 17 | "%d hours ago" = "%d годин тому"; 18 | 19 | /* Y > 1 AND Y < 5 AND (XY < 10 OR XY > 20); */ 20 | "%d _hours ago" = "%d години тому"; 21 | 22 | /* Y == 1 AND XY != 11; */ 23 | "%d __hours ago" = "%d годину тому"; 24 | 25 | 26 | /* Y == 0 OR Y > 4 OR (XY > 10 AND XY < 15); */ 27 | "%d minutes ago" = "%d хвилин тому"; 28 | 29 | /* Y > 1 AND Y < 5 AND (XY < 10 OR XY > 20); */ 30 | "%d _minutes ago" = "%d хвилини тому"; 31 | 32 | /* Y == 1 AND XY != 11; */ 33 | "%d __minutes ago" = "%d хвилину тому"; 34 | 35 | 36 | /* Y == 0 OR Y > 4 OR (XY > 10 AND XY < 15); */ 37 | "%d months ago" = "%d місяців тому"; 38 | 39 | /* Y > 1 AND Y < 5 AND (XY < 10 OR XY > 20); */ 40 | "%d _months ago" = "%d місяця тому"; 41 | 42 | /* Y == 1 AND XY != 11; */ 43 | "%d __months ago" = "%d місяць тому"; 44 | 45 | 46 | /* Y == 0 OR Y > 4 OR (XY > 10 AND XY < 15); */ 47 | "%d seconds ago" = "%d секунд тому"; 48 | 49 | /* Y > 1 AND Y < 5 AND (XY < 10 OR XY > 20); */ 50 | "%d _seconds ago" = "%d секунди тому"; 51 | 52 | /* Y == 1 AND XY != 11; */ 53 | "%d __seconds ago" = "%d секунду тому"; 54 | 55 | 56 | /* Y == 0 OR Y > 4 OR (XY > 10 AND XY < 15); */ 57 | "%d weeks ago" = "%d тижднів тому"; 58 | 59 | /* Y > 1 AND Y < 5 AND (XY < 10 OR XY > 20); */ 60 | "%d _weeks ago" = "%d тиждні тому"; 61 | 62 | /* Y == 1 AND XY != 11; */ 63 | "%d __weeks ago" = "%d тиждень тому"; 64 | 65 | 66 | /* Y == 0 OR Y > 4 OR (XY > 10 AND XY < 15); */ 67 | "%d years ago" = "%d років тому"; 68 | 69 | /* Y > 1 AND Y < 5 AND (XY < 10 OR XY > 20); */ 70 | "%d _years ago" = "%d роки тому"; 71 | 72 | /* Y == 1 AND XY != 11; */ 73 | "%d __years ago" = "%d рік тому"; 74 | 75 | 76 | /* No comment provided by engineer. */ 77 | "A minute ago" = "Хвилину тому"; 78 | 79 | /* No comment provided by engineer. */ 80 | "An hour ago" = "Годину тому"; 81 | 82 | /* No comment provided by engineer. */ 83 | "Just now" = "Щойно"; 84 | 85 | /* No comment provided by engineer. */ 86 | "Last month" = "Місяць тому"; 87 | 88 | /* No comment provided by engineer. */ 89 | "Last week" = "Тиждень тому"; 90 | 91 | /* No comment provided by engineer. */ 92 | "Last year" = "Рік тому"; 93 | 94 | /* No comment provided by engineer. */ 95 | "Yesterday" = "Вчора"; 96 | 97 | /* No comment provided by engineer. */ 98 | "1 year ago" = "1 рік тому"; 99 | 100 | /* No comment provided by engineer. */ 101 | "1 month ago" = "1 місяць тому"; 102 | 103 | /* No comment provided by engineer. */ 104 | "1 week ago" = "1 тиждень тому"; 105 | 106 | /* No comment provided by engineer. */ 107 | "1 day ago" = "1 день тому"; 108 | 109 | /* No comment provided by engineer. */ 110 | "This morning" = "Цього ранку"; 111 | 112 | /* No comment provided by engineer. */ 113 | "This afternoon" = "Сьогодні вдень"; 114 | 115 | /* No comment provided by engineer. */ 116 | "Today" = "Сьогодні"; 117 | 118 | /* No comment provided by engineer. */ 119 | "This week" = "Цього тиждня"; 120 | 121 | /* No comment provided by engineer. */ 122 | "This month" = "Цього місяця"; 123 | 124 | /* No comment provided by engineer. */ 125 | "This year" = "Цього року"; 126 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.bundle/ru.lproj/NSDateTimeAgo.strings: -------------------------------------------------------------------------------- 1 | /* 2 | RULES: 3 | Assume value for (seconds, hours, minutes, days, weeks, months or years) is XXXY, Y is last digit, XY is last two digits; 4 | */ 5 | 6 | /* Y == 0 OR Y > 4 OR (XY > 10 AND XY < 15); */ 7 | "%d days ago" = "%d дней назад"; 8 | 9 | /* Y > 1 AND Y < 5 AND (XY < 10 OR XY > 20); */ 10 | "%d _days ago" = "%d дня назад"; 11 | 12 | /* Y == 1 AND XY != 11; */ 13 | "%d __days ago" = "%d день назад"; 14 | 15 | 16 | /* Y == 0 OR Y > 4 OR (XY > 10 AND XY < 15); */ 17 | "%d hours ago" = "%d часов назад"; 18 | 19 | /* Y > 1 AND Y < 5 AND (XY < 10 OR XY > 20); */ 20 | "%d _hours ago" = "%d часа назад"; 21 | 22 | /* Y == 1 AND XY != 11; */ 23 | "%d __hours ago" = "%d час назад"; 24 | 25 | 26 | /* Y == 0 OR Y > 4 OR (XY > 10 AND XY < 15); */ 27 | "%d minutes ago" = "%d минут назад"; 28 | 29 | /* Y > 1 AND Y < 5 AND (XY < 10 OR XY > 20); */ 30 | "%d _minutes ago" = "%d минуты назад"; 31 | 32 | /* Y == 1 AND XY != 11; */ 33 | "%d __minutes ago" = "%d минуту назад"; 34 | 35 | 36 | /* Y == 0 OR Y > 4 OR (XY > 10 AND XY < 15); */ 37 | "%d months ago" = "%d месяцев назад"; 38 | 39 | /* Y > 1 AND Y < 5 AND (XY < 10 OR XY > 20); */ 40 | "%d _months ago" = "%d месяца назад"; 41 | 42 | /* Y == 1 AND XY != 11; */ 43 | "%d __months ago" = "%d месяц назад"; 44 | 45 | 46 | /* Y == 0 OR Y > 4 OR (XY > 10 AND XY < 15); */ 47 | "%d seconds ago" = "%d секунд назад"; 48 | 49 | /* Y > 1 AND Y < 5 AND (XY < 10 OR XY > 20); */ 50 | "%d _seconds ago" = "%d секунды назад"; 51 | 52 | /* Y == 1 AND XY != 11; */ 53 | "%d __seconds ago" = "%d секунду назад"; 54 | 55 | 56 | /* Y == 0 OR Y > 4 OR (XY > 10 AND XY < 15); */ 57 | "%d weeks ago" = "%d недель назад"; 58 | 59 | /* Y > 1 AND Y < 5 AND (XY < 10 OR XY > 20); */ 60 | "%d _weeks ago" = "%d недели назад"; 61 | 62 | /* Y == 1 AND XY != 11; */ 63 | "%d __weeks ago" = "%d неделю назад"; 64 | 65 | 66 | /* Y == 0 OR Y > 4 OR (XY > 10 AND XY < 15); */ 67 | "%d years ago" = "%d лет назад"; 68 | 69 | /* Y > 1 AND Y < 5 AND (XY < 10 OR XY > 20); */ 70 | "%d _years ago" = "%d года назад"; 71 | 72 | /* Y == 1 AND XY != 11; */ 73 | "%d __years ago" = "%d год назад"; 74 | 75 | 76 | /* No comment provided by engineer. */ 77 | "A minute ago" = "Минуту назад"; 78 | 79 | /* No comment provided by engineer. */ 80 | "An hour ago" = "Час назад"; 81 | 82 | /* No comment provided by engineer. */ 83 | "Just now" = "Только что"; 84 | 85 | /* No comment provided by engineer. */ 86 | "Last month" = "Месяц назад"; 87 | 88 | /* No comment provided by engineer. */ 89 | "Last week" = "Неделю назад"; 90 | 91 | /* No comment provided by engineer. */ 92 | "Last year" = "Год назад"; 93 | 94 | /* No comment provided by engineer. */ 95 | "Yesterday" = "Вчера"; 96 | 97 | /* No comment provided by engineer. */ 98 | "1 year ago" = "1 год назад"; 99 | 100 | /* No comment provided by engineer. */ 101 | "1 month ago" = "1 месяц назад"; 102 | 103 | /* No comment provided by engineer. */ 104 | "1 week ago" = "1 неделю назад"; 105 | 106 | /* No comment provided by engineer. */ 107 | "1 day ago" = "1 день назад"; 108 | 109 | /* No comment provided by engineer. */ 110 | "This morning" = "Этим утром"; 111 | 112 | /* No comment provided by engineer. */ 113 | "This afternoon" = "Этим днём"; 114 | 115 | /* No comment provided by engineer. */ 116 | "Today" = "Сегодня"; 117 | 118 | /* No comment provided by engineer. */ 119 | "This week" = "На этой неделе"; 120 | 121 | /* No comment provided by engineer. */ 122 | "This month" = "В этом месяце"; 123 | 124 | /* No comment provided by engineer. */ 125 | "This year" = "В этом году"; 126 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMomentTests/FromNowTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FromNowTests.swift 3 | // SwiftMoment 4 | // 5 | // Created by Madhava Jay on 07/06/2016. 6 | // Copyright © 2016 Adrian Kosmaczewski. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import XCTest 11 | import SwiftMoment 12 | 13 | class FromNowTests: XCTestCase { 14 | 15 | override func setUp() { 16 | super.setUp() 17 | } 18 | 19 | override func tearDown() { 20 | super.tearDown() 21 | } 22 | 23 | func testFromNowEnglish() { 24 | let now = Date() 25 | let nowMoment = getLocalEnglishMoment(now) 26 | XCTAssertEqual(nowMoment.fromNow(), "Just now") 27 | 28 | let nowSeconds = now.addingTimeInterval(TimeInterval(-50)) 29 | let secondsMoment = getLocalEnglishMoment(nowSeconds) 30 | XCTAssertEqual(secondsMoment.fromNow(), "50 seconds ago") 31 | 32 | let nowSeconds2 = now.addingTimeInterval(TimeInterval(-90)) 33 | let secondsMoment2 = getLocalEnglishMoment(nowSeconds2) 34 | XCTAssertEqual(secondsMoment2.fromNow(), "A minute ago") 35 | 36 | let nowMinutes = now.addingTimeInterval(TimeInterval(-500)) 37 | let minutesMoment = getLocalEnglishMoment(nowMinutes) 38 | XCTAssertEqual(minutesMoment.fromNow(), "8 minutes ago") 39 | 40 | let hourSecs: Double = 3600 41 | 42 | let nowMinutes2 = now.addingTimeInterval(TimeInterval(-(hourSecs * 1.5))) 43 | let minutesMoment2 = getLocalEnglishMoment(nowMinutes2) 44 | XCTAssertEqual(minutesMoment2.fromNow(), "An hour ago") 45 | 46 | let nowMinutes3 = now.addingTimeInterval(TimeInterval(-(hourSecs * 6))) 47 | let minutesMoment3 = getLocalEnglishMoment(nowMinutes3) 48 | XCTAssertEqual(minutesMoment3.fromNow(), "6 hours ago") 49 | 50 | let nowHours = now.addingTimeInterval(TimeInterval(-(hourSecs * 25))) 51 | let hoursMoment = getLocalEnglishMoment(nowHours) 52 | XCTAssertEqual(hoursMoment.fromNow(), "Yesterday") 53 | 54 | let nowHours2 = now.addingTimeInterval(TimeInterval(-(hourSecs * 48))) 55 | let hoursMoment2 = getLocalEnglishMoment(nowHours2) 56 | XCTAssertEqual(hoursMoment2.fromNow(), "2 days ago") 57 | 58 | let daySecs = hourSecs * 24 59 | 60 | let nowDays = now.addingTimeInterval(TimeInterval(-(daySecs * 7))) 61 | let daysMoment = getLocalEnglishMoment(nowDays) 62 | XCTAssertEqual(daysMoment.fromNow(), "Last week") 63 | 64 | let nowWeeks = now.addingTimeInterval(TimeInterval(-(daySecs * 14))) 65 | let weeksMoment = getLocalEnglishMoment(nowWeeks) 66 | XCTAssertEqual(weeksMoment.fromNow(), "2 weeks ago") 67 | 68 | let nowWeeks2 = now.addingTimeInterval(TimeInterval(-(daySecs * 50))) 69 | let weeksMoment2 = getLocalEnglishMoment(nowWeeks2) 70 | XCTAssertEqual(weeksMoment2.fromNow(), "Last month") 71 | 72 | let weekSecs = daySecs * 7 73 | 74 | let nowMonths = now.addingTimeInterval(TimeInterval(-(weekSecs * 10))) 75 | let monthsMoment = getLocalEnglishMoment(nowMonths) 76 | XCTAssertEqual(monthsMoment.fromNow(), "2 months ago") 77 | 78 | let nowMonths2 = now.addingTimeInterval(TimeInterval(-(weekSecs * 60))) 79 | let monthsMoment2 = getLocalEnglishMoment(nowMonths2) 80 | XCTAssertEqual(monthsMoment2.fromNow(), "Last year") 81 | 82 | let nowMonths3 = now.addingTimeInterval(TimeInterval(-(weekSecs * 160))) 83 | let monthsMoment3 = getLocalEnglishMoment(nowMonths3) 84 | XCTAssertEqual(monthsMoment3.fromNow(), "3 years ago") 85 | } 86 | 87 | func getLocalEnglishMoment(_ date: Date) -> Moment { 88 | return moment(date, timeZone: TimeZone.current, 89 | locale: Locale(identifier: "en")) 90 | } 91 | 92 | func testFromNowHebrew() { 93 | let mom = moment(Date(), timeZone: TimeZone.current, 94 | locale: Locale(identifier: "he")) 95 | XCTAssertEqual(mom.fromNow(), "ממש עכשיו") 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/Duration.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Duration.swift 3 | // SwiftMoment 4 | // 5 | // Created by Adrian on 19/01/15. 6 | // Copyright (c) 2015 Adrian Kosmaczewski. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /// Just like Moment wraps a Date, Duration wraps a TimeInterval. 12 | public struct Duration: Equatable { 13 | internal let interval: TimeInterval 14 | 15 | /// Initializes a new instance. 16 | /// 17 | /// - parameter value: A TimeInterval value. 18 | /// 19 | /// - returns: A new Duration instance. 20 | public init(value: TimeInterval) { 21 | self.interval = value 22 | } 23 | 24 | /// Initializes a new instance. 25 | /// 26 | /// - parameter value: An integer value, representing seconds. 27 | /// 28 | /// - returns: A new Duration instance. 29 | public init(value: Int) { 30 | self.interval = TimeInterval(value) 31 | } 32 | 33 | /// The amount of years of the current instance. 34 | public var years: Double { 35 | return interval / Moment.yearInSeconds // 365 days 36 | } 37 | 38 | /// The amount of quarters of the current instance. 39 | public var quarters: Double { 40 | return interval / Moment.quarterInSeconds // 3 months 41 | } 42 | 43 | /// The amount of months of the current instance. 44 | public var months: Double { 45 | return interval / Moment.monthInSeconds // 30 days 46 | } 47 | 48 | /// The amount of days of the current instance. 49 | public var days: Double { 50 | return interval / Moment.dayInSeconds // 24 hours 51 | } 52 | 53 | /// The amount of hours of the current instance. 54 | public var hours: Double { 55 | return interval / Moment.hourInSeconds // 60 minutes 56 | } 57 | 58 | /// The amount of minutes of the current instance. 59 | public var minutes: Double { 60 | return interval / Moment.minuteInSeconds 61 | } 62 | 63 | /// The amount of seconds of the current instance. 64 | public var seconds: Double { 65 | return interval 66 | } 67 | 68 | /// Returns a Moment that happened a current Duration ago. 69 | /// 70 | /// - returns: A new Moment instance. 71 | public func ago() -> Moment { 72 | return moment().subtract(self) 73 | } 74 | 75 | /// Adds the specified duration to the current instance. 76 | /// 77 | /// - parameter duration: A Duration value to add to the current one. 78 | /// 79 | /// - returns: A new Duration value. 80 | public func add(_ duration: Duration) -> Duration { 81 | return Duration(value: self.interval + duration.interval) 82 | } 83 | 84 | /// Substracts the specified duration to the current instance. 85 | /// 86 | /// - parameter duration: A Duration value to substract to the current one. 87 | /// 88 | /// - returns: A new Duration value. 89 | public func subtract(_ duration: Duration) -> Duration { 90 | return Duration(value: self.interval - duration.interval) 91 | } 92 | 93 | /// Specifies whether the current value is equal to the one passed in parameter. 94 | /// 95 | /// - parameter duration: The Duration instance to compare to. 96 | /// 97 | /// - returns: A boolean; true if the parameter is equal, false otherwise. 98 | public func isEqualTo(_ duration: Duration) -> Bool { 99 | return self.interval == duration.interval 100 | } 101 | 102 | } 103 | 104 | extension Duration: CustomStringConvertible { 105 | 106 | /// A textual representation of this instance. 107 | public var description: String { 108 | let formatter = DateComponentsFormatter() 109 | formatter.calendar = Calendar(identifier: Calendar.Identifier.gregorian) 110 | formatter.calendar?.timeZone = TimeZone(abbreviation: "UTC")! 111 | formatter.allowedUnits = [.year, .month, .weekOfMonth, .day, .hour, .minute, .second] 112 | 113 | let referenceDate = Date(timeIntervalSinceReferenceDate: 0) 114 | let intervalDate = Date(timeInterval: self.interval, since: referenceDate) 115 | return formatter.string(from: referenceDate, to: intervalDate)! 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment.xcodeproj/xcshareddata/xcschemes/SwiftMoment iOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 46 | 47 | 49 | 55 | 56 | 57 | 58 | 59 | 65 | 66 | 67 | 68 | 69 | 70 | 81 | 82 | 88 | 89 | 90 | 91 | 92 | 93 | 99 | 100 | 106 | 107 | 108 | 109 | 111 | 112 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment.xcodeproj/xcshareddata/xcschemes/SwiftMoment tvOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 46 | 47 | 49 | 55 | 56 | 57 | 58 | 59 | 65 | 66 | 67 | 68 | 69 | 70 | 81 | 82 | 88 | 89 | 90 | 91 | 92 | 93 | 99 | 100 | 106 | 107 | 108 | 109 | 111 | 112 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment.xcodeproj/xcshareddata/xcschemes/SwiftMoment macOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 46 | 47 | 49 | 55 | 56 | 57 | 58 | 59 | 65 | 66 | 67 | 68 | 69 | 70 | 81 | 82 | 88 | 89 | 90 | 91 | 92 | 93 | 99 | 100 | 106 | 107 | 108 | 109 | 111 | 112 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SwiftMoment 2 | 3 | [![Join the chat at https://gitter.im/SwiftMoment/Lobby](https://badges.gitter.im/SwiftMoment/Lobby.svg)](https://gitter.im/SwiftMoment/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Build Status](https://travis-ci.org/akosma/SwiftMoment.svg?branch=master)](https://travis-ci.org/akosma/SwiftMoment) 4 | [![CocoaPods Compatible](https://img.shields.io/cocoapods/v/SwiftMoment.svg)](https://img.shields.io/cocoapods/v/SwiftMoment) 5 | [![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 6 | [![Platform](https://img.shields.io/cocoapods/p/SwiftMoment.svg?style=flat)](http://cocoadocs.org/docsets/SwiftMoment) 7 | [![swiftyness](https://img.shields.io/badge/pure-swift-ff3f26.svg?style=flat)](https://swift.org/) 8 | 9 | This framework is inspired by [Moment.js](http://momentjs.com). Its 10 | objectives are the following: 11 | 12 | - Simplify the manipulation and readability of date and interval values. 13 | - Provide help when parsing dates from various string representations. 14 | - Simplifying the formatting of date information into strings. 15 | - Streamlining getting date components (day, month, etc.) from dates and 16 | time intervals. 17 | 18 | Important: This framework supports iOS 9+, macOS 10.11+, tvOS 9+, watchOS 2+, Xcode 8 and Swift 3. 19 | 20 | ## Installation 21 | 22 | SwiftMoment is compatible with 23 | [Carthage](http://github.com/Carthage/Carthage) and 24 | [CocoaPods](http://cocoapods.org/). With CocoaPods, just add this to 25 | your Podfile: 26 | 27 | ```ruby 28 | pod 'SwiftMoment' 29 | ``` 30 | 31 | SwiftMoment can also be used via the [Swift Package Manager](https://swift.org/package-manager/). 32 | Just add it to the dependencies in your Package.swift file: 33 | 34 | ```Swift 35 | let package = Package( 36 | name: "MyPackage", 37 | dependencies: [ 38 | ... 39 | .package(url: "https://github.com/akosma/SwiftMoment.git", from: "0.7.1"), 40 | ], 41 | ... 42 | ) 43 | ``` 44 | 45 | 46 | ## Mac OS X Notes 47 | 48 | - Drag the created .framework file into the Xcode Project, be sure to tick 'Copy Files to Directory' 49 | - In the containing applications target, add a new 'Copy File Build Phase' 50 | - Set the 'Destination' to 'Frameworks' 51 | - Drag in the created .framework 52 | 53 | ## Examples 54 | 55 | To use this library, just `import SwiftMoment` in your application. 56 | 57 | To create new moment instances: 58 | 59 | ```Swift 60 | let now = moment() 61 | let yesterday = moment("2015-01-19") 62 | ``` 63 | 64 | By default, moments are initialized with the current date and time. You 65 | can create moments for any... moment in the future or the past; you can 66 | do that by passing strings in different formats: 67 | 68 | ```Swift 69 | let yesterday = moment("2015-01-19") 70 | ``` 71 | 72 | You can also do it by directly specifying the components manually: 73 | 74 | ```Swift 75 | let today = moment([2015, 01, 19, 20, 45, 34]) 76 | ``` 77 | 78 | You can also use a dictionary with the following keys: 79 | 80 | ```Swift 81 | let obj = moment(["year": 2015, 82 | "second": 34, 83 | "month": 01, 84 | "minute": 45, 85 | "hour": 20, 86 | "day": 19 87 | ]) 88 | ``` 89 | 90 | When using a `[String: Int]` dictionary, the order of the keys does not 91 | matter. Moreover, only the keys above are taken into account, and any 92 | other information is ignored. 93 | 94 | There is also an extension to the `Int` type in Swift, used to create 95 | `Duration` values directly from an integer value: 96 | 97 | ```Swift 98 | let duration = 5.hours + 56.minutes 99 | ``` 100 | 101 | ## Architecture 102 | 103 | The two most important components of this library are the `Moment` and 104 | `Duration` structures. `Moment` wraps an `NSDate` instance, while 105 | `Duration` wraps an `NSTimeInterval` value. 106 | 107 | Both `Moment` and `Duration` comply with the `Comparable` protocols, and 108 | include all the required operators. In addition, `Moment` instances can 109 | be subtracted from one another (which yields a `Duration`) and 110 | `Duration` instances can be added to `Moments` to create new moments. 111 | 112 | `Moments` and `Durations` are made as immutable as possible. 113 | 114 | ## Tests 115 | 116 | Swift Moment includes a suite of tests showing how to use the different 117 | functions of the framework. 118 | 119 | To run the Linux tests in a macOS environment, please use the included Dockerfile: 120 | 121 | ``` 122 | docker build --tag swiftmoment . 123 | docker run --rm swiftmoment 124 | ``` 125 | 126 | ## Playground 127 | 128 | A playground is included in the project to learn how to use the library. 129 | 130 | ## Differences with [Moment.js](http://momentjs.com) 131 | 132 | - Format strings `DD` and `dd` do not yield the same results. 133 | 134 | ## Contributors 135 | 136 | Lots of people are actively helping in the development of this library; 137 | please check the 138 | [CONTRIBUTORS](https://github.com/akosma/SwiftMoment/blob/master/CONTRIBUTORS.md) 139 | file for the full list! Thanks to all :) 140 | 141 | ## License 142 | 143 | This project is distributed under a BSD license. See the LICENSE file 144 | for details. 145 | 146 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/Operators.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Operators.swift 3 | // SwiftMoment 4 | // 5 | // Created by Adrian on 19/01/15. 6 | // Copyright (c) 2015 Adrian Kosmaczewski. All rights reserved. 7 | // 8 | 9 | 10 | /// Compares both Moments for equality. 11 | /// 12 | /// - parameter lhs: The Moment at the left hand side. 13 | /// - parameter rhs: The Moment at the right hand side. 14 | /// 15 | /// - returns: A boolean; true if equal, false otherwise. 16 | public func == (lhs: Moment, rhs: Moment) -> Bool { 17 | return lhs.isEqualTo(rhs) 18 | } 19 | 20 | /// Compares both Moments for inequality. 21 | /// 22 | /// - parameter lhs: The Moment at the left hand side. 23 | /// - parameter rhs: The Moment at the right hand side. 24 | /// 25 | /// - returns: A boolean; true if inequal, false otherwise. 26 | public func != (lhs: Moment, rhs: Moment) -> Bool { 27 | return !lhs.isEqualTo(rhs) 28 | } 29 | 30 | /// Compares both Moments for similarity. 31 | /// 32 | /// - parameter lhs: The Moment at the left hand side. 33 | /// - parameter rhs: The Moment at the right hand side. 34 | /// 35 | /// - returns: A boolean; true if close by, false otherwise. 36 | public func ~= (lhs: Moment, rhs: Moment) -> Bool { 37 | return lhs.isCloseTo(rhs) 38 | } 39 | 40 | /// Compares both Moments. 41 | /// 42 | /// - parameter lhs: The Moment at the left hand side. 43 | /// - parameter rhs: The Moment at the right hand side. 44 | /// 45 | /// - returns: A boolean; true if lhs is later than rhs, false otherwise. 46 | public func > (lhs: Moment, rhs: Moment) -> Bool { 47 | return lhs.intervalSince(rhs).interval > 0 48 | } 49 | 50 | /// Compares both Moments. 51 | /// 52 | /// - parameter lhs: The Moment at the left hand side. 53 | /// - parameter rhs: The Moment at the right hand side. 54 | /// 55 | /// - returns: A boolean; true if lhs is earlier than rhs, false otherwise. 56 | public func < (lhs: Moment, rhs: Moment) -> Bool { 57 | return lhs.intervalSince(rhs).interval < 0 58 | } 59 | 60 | /// Compares both Moments. 61 | /// 62 | /// - parameter lhs: The Moment at the left hand side. 63 | /// - parameter rhs: The Moment at the right hand side. 64 | /// 65 | /// - returns: A boolean; true if lhs is later or equal than rhs, false otherwise. 66 | public func >= (lhs: Moment, rhs: Moment) -> Bool { 67 | return lhs.intervalSince(rhs).interval >= 0 68 | } 69 | 70 | /// Compares both Moments. 71 | /// 72 | /// - parameter lhs: The Moment at the left hand side. 73 | /// - parameter rhs: The Moment at the right hand side. 74 | /// 75 | /// - returns: A boolean; true if lhs is earlier or equal than rhs, false otherwise. 76 | public func <= (lhs: Moment, rhs: Moment) -> Bool { 77 | return lhs.intervalSince(rhs).interval <= 0 78 | } 79 | 80 | /// Substracts two Moment instance and returns the Duration between both. 81 | /// 82 | /// - parameter lhs: The Moment at the left hand side. 83 | /// - parameter rhs: The Moment at the right hand side. 84 | /// 85 | /// - returns: The Duration between two moments. 86 | public func - (lhs: Moment, rhs: Moment) -> Duration { 87 | return lhs.intervalSince(rhs) 88 | } 89 | 90 | /// Adds the Duration to the Moment. 91 | /// 92 | /// - parameter lhs: A Moment value. 93 | /// - parameter rhs: A Duration to add to the Moment. 94 | /// 95 | /// - returns: A new Moment instance. 96 | public func + (lhs: Moment, rhs: Duration) -> Moment { 97 | return lhs.add(rhs) 98 | } 99 | 100 | /// Adds the Duration to the Moment. 101 | /// 102 | /// - parameter lhs: A Duration to substract to the Moment. 103 | /// - parameter rhs: A Moment value. 104 | /// 105 | /// - returns: A new Moment instance. 106 | public func + (lhs: Duration, rhs: Moment) -> Moment { 107 | return rhs.add(lhs) 108 | } 109 | 110 | /// Substracts the Duration to the Moment. 111 | /// 112 | /// - parameter lhs: A Moment value. 113 | /// - parameter rhs: A Duration to substract to the Moment. 114 | /// 115 | /// - returns: A new Moment instance. 116 | public func - (lhs: Moment, rhs: Duration) -> Moment { 117 | return lhs.subtract(rhs) 118 | } 119 | 120 | /// Substract the Duration to the Moment. 121 | /// 122 | /// - parameter lhs: A Duration to substract to the Moment. 123 | /// - parameter rhs: A Moment value. 124 | /// 125 | /// - returns: A new Moment instance. 126 | public func - (lhs: Duration, rhs: Moment) -> Moment { 127 | return rhs.subtract(lhs) 128 | } 129 | 130 | /// Compares two Durations for equality. 131 | /// 132 | /// - parameter lhs: The Duration at the left hand side. 133 | /// - parameter rhs: The Duration at the right hand side. 134 | /// 135 | /// - returns: A boolean; true if the Durations are the same, false otherwise. 136 | public func == (lhs: Duration, rhs: Duration) -> Bool { 137 | return lhs.isEqualTo(rhs) 138 | } 139 | 140 | /// Adds the durations. 141 | /// 142 | /// - parameter lhs: The Duration at the left hand side. 143 | /// - parameter rhs: The Duration at the right hand side. 144 | /// 145 | /// - returns: A new Duration value. 146 | public func + (lhs: Duration, rhs: Duration) -> Duration { 147 | return lhs.add(rhs) 148 | } 149 | 150 | /// Substracts the durations. 151 | /// 152 | /// - parameter lhs: The Duration at the left hand side. 153 | /// - parameter rhs: The Duration at the right hand side. 154 | /// 155 | /// - returns: A new Duration value. 156 | public func - (lhs: Duration, rhs: Duration) -> Duration { 157 | return lhs.subtract(rhs) 158 | } 159 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMoment/MomentFromNow.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MomentFromNow.swift 3 | // SwiftMoment 4 | // 5 | // Created by Madhava Jay on 07/06/2016. 6 | // Copyright © 2016 Adrian Kosmaczewski. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | // needed to dynamically select the bundle below 12 | class MomentBundle: NSObject {} 13 | 14 | extension Moment { 15 | 16 | /// Returns a localized string specifying the time duration between 17 | /// the current instance and the present moment. 18 | /// 19 | /// - returns: A localized string. 20 | public func fromNow() -> String { 21 | let timeDiffDuration = moment().intervalSince(self) 22 | let deltaSeconds = timeDiffDuration.seconds 23 | 24 | var value: Double! 25 | 26 | if deltaSeconds < 5 { 27 | // Just Now 28 | return NSDateTimeAgoLocalizedStrings("Just now") 29 | 30 | } 31 | else if deltaSeconds < Moment.minuteInSeconds { 32 | // Seconds Ago 33 | return stringFromFormat("%%d %@seconds ago", withValue: Int(deltaSeconds)) 34 | 35 | } 36 | else if deltaSeconds < (Moment.minuteInSeconds * 2) { 37 | // A Minute Ago 38 | return NSDateTimeAgoLocalizedStrings("A minute ago") 39 | 40 | } 41 | else if deltaSeconds < Moment.hourInSeconds { 42 | // Minutes Ago 43 | return stringFromFormat("%%d %@minutes ago", withValue: Int(deltaSeconds / Moment.minuteInSeconds)) 44 | 45 | } 46 | else if deltaSeconds < (Moment.hourInSeconds * 2) { 47 | // An Hour Ago 48 | return NSDateTimeAgoLocalizedStrings("An hour ago") 49 | 50 | } 51 | else if deltaSeconds < Moment.dayInSeconds { 52 | // Hours Ago 53 | value = floor(deltaSeconds / Moment.hourInSeconds) 54 | return stringFromFormat("%%d %@hours ago", withValue: Int(value)) 55 | 56 | } 57 | else if deltaSeconds < (Moment.dayInSeconds * 2) { 58 | // Yesterday 59 | return NSDateTimeAgoLocalizedStrings("Yesterday") 60 | 61 | } 62 | else if deltaSeconds < Moment.weekInSeconds { 63 | // Days Ago 64 | value = floor(deltaSeconds / Moment.dayInSeconds) 65 | return stringFromFormat("%%d %@days ago", withValue: Int(value)) 66 | 67 | } 68 | else if deltaSeconds < (Moment.weekInSeconds * 2) { 69 | // Last Week 70 | return NSDateTimeAgoLocalizedStrings("Last week") 71 | 72 | } 73 | else if deltaSeconds < Moment.monthInSeconds { 74 | // Weeks Ago 75 | value = floor(deltaSeconds / Moment.weekInSeconds) 76 | return stringFromFormat("%%d %@weeks ago", withValue: Int(value)) 77 | 78 | } 79 | else if deltaSeconds < (Moment.dayInSeconds * 61) { 80 | // Last month 81 | return NSDateTimeAgoLocalizedStrings("Last month") 82 | 83 | } 84 | else if deltaSeconds < Moment.yearInSeconds { 85 | // Month Ago 86 | value = floor(deltaSeconds / Moment.monthInSeconds) 87 | return stringFromFormat("%%d %@months ago", withValue: Int(value)) 88 | 89 | } 90 | else if deltaSeconds < (Moment.yearInSeconds * 2) { 91 | // Last Year 92 | return NSDateTimeAgoLocalizedStrings("Last year") 93 | } 94 | 95 | // Years Ago 96 | value = floor(deltaSeconds / Moment.yearInSeconds) 97 | return stringFromFormat("%%d %@years ago", withValue: Int(value)) 98 | } 99 | 100 | private func stringFromFormat(_ format: String, withValue value: Int) -> String { 101 | let localeFormat = String(format: format, 102 | getLocaleFormatUnderscoresWithValue(Double(value))) 103 | return String(format: NSDateTimeAgoLocalizedStrings(localeFormat), value) 104 | } 105 | 106 | private func NSDateTimeAgoLocalizedStrings(_ key: String) -> String { 107 | // get framework bundle 108 | guard let bundleIdentifier = Bundle(for: MomentBundle.self).bundleIdentifier else { 109 | return "" 110 | } 111 | 112 | guard let frameworkBundle = Bundle(identifier: bundleIdentifier) else { 113 | return "" 114 | } 115 | 116 | guard let resourcePath = frameworkBundle.resourcePath else { 117 | return "" 118 | } 119 | 120 | let bundleName = "MomentFromNow.bundle" 121 | let path = URL(fileURLWithPath: resourcePath).appendingPathComponent(bundleName) 122 | guard let bundle = Bundle(url: path) else { 123 | return "" 124 | } 125 | 126 | if let languageBundle = getLanguageBundle(bundle) { 127 | return languageBundle.localizedString(forKey: key, value: "", table: "NSDateTimeAgo") 128 | } 129 | 130 | return "" 131 | } 132 | 133 | private func getLanguageBundle(_ bundle: Bundle) -> Bundle? { 134 | let localeIdentifer = self.locale.identifier 135 | if let languagePath = bundle.path(forResource: localeIdentifer, ofType: "lproj") { 136 | return Bundle(path: languagePath) 137 | } 138 | 139 | let langDict = Locale.components(fromIdentifier: localeIdentifer) 140 | let languageCode = langDict["kCFLocaleLanguageCodeKey"] 141 | if let languagePath = bundle.path(forResource: languageCode, ofType: "lproj") { 142 | return Bundle(path: languagePath) 143 | } 144 | 145 | return nil 146 | } 147 | 148 | private func getLocaleFormatUnderscoresWithValue(_ value: Double) -> String { 149 | guard let languageCode = self.locale.languageCode else { 150 | return "" 151 | } 152 | 153 | if languageCode == "ru" { 154 | let xy = Int(floor(value)) % 100 155 | let y = Int(floor(value)) % 10 156 | 157 | if y == 0 || y > 4 || (xy > 10 && xy < 15) { 158 | return "" 159 | } 160 | 161 | if y > 1 && y < 5 && (xy < 10 || xy > 20) { 162 | return "_" 163 | } 164 | 165 | if y == 1 && xy != 11 { 166 | return "__" 167 | } 168 | } 169 | 170 | return "" 171 | } 172 | 173 | } 174 | -------------------------------------------------------------------------------- /Book/lib.rb: -------------------------------------------------------------------------------- 1 | # Parse command line arguments and returns an OpenStruct 2 | def parse_arguments 3 | opts = OpenStruct.new 4 | OptionParser.new do |opt| 5 | opt.on('-i', '--in FILENAME', 'Input in Markdown format') { |o| opts.input = o } 6 | opt.on('-o', '--out FILENAME', 'Output in Playgroundbook format') { |o| opts.output = o } 7 | opt.on('-v', '--verbose', 'Toggle verbose mode') { |o| opts.verbose = o } 8 | end.parse! 9 | 10 | opts 11 | end 12 | 13 | # Validate command line arguments 14 | # If this method returns false, the program should exit 15 | def validate_options(opts) 16 | if opts.input == nil 17 | return false, "Input file missing; `generator -h` for help" 18 | end 19 | 20 | if !File.exist?(opts.input) 21 | return false, "Wrong input file" 22 | end 23 | 24 | if opts.output == nil 25 | opts.output = "Book.playgroundbook" 26 | puts "Output filename not provided, using #{opts.output}" if opts.verbose 27 | end 28 | 29 | if !opts.output.end_with?(".playgroundbook") 30 | opts.output = "#{opts.output}.playgroundbook" 31 | puts "Using #{opts.output} as output filename" if opts.verbose 32 | end 33 | 34 | if File.exist?(opts.output) 35 | return false, "File #{opts.output} already exists. Exiting." 36 | end 37 | 38 | if opts.chapter == nil 39 | opts.chapter = "Chapter.playgroundchapter" 40 | puts "Using #{opts.chapter} as chapter name" if opts.verbose 41 | end 42 | 43 | return true, nil 44 | end 45 | 46 | # Parse the input file and split it using the HR tags 47 | def read_input(opts, separator = :hr) 48 | text = File.read(opts.input) 49 | puts "Reading #{opts.input} as input" if opts.verbose 50 | source = Kramdown::Document.new(text) 51 | 52 | pages = [] 53 | current_page = { :doc => Kramdown::Document.new(''), :title => "" } 54 | puts "Parsing #{opts.input}" if opts.verbose 55 | source.root.children.each do |element| 56 | if element.type == separator 57 | pages << current_page 58 | current_page = { :doc => Kramdown::Document.new(''), :title => "" } 59 | elsif element.type == :header && element.options[:level] == 1 && current_page[:title] == "" 60 | # We grab the first

element in the page and set it as the title 61 | # of the current page. 62 | current_page[:doc].root.children << element 63 | current_page[:title] = element.options[:raw_text] 64 | else 65 | current_page[:doc].root.children << element 66 | end 67 | end 68 | 69 | pages << current_page 70 | puts "Found #{pages.count} slides on #{opts.input}" if opts.verbose 71 | pages 72 | end 73 | 74 | # Create the basic folder structure 75 | def create_structure(opts) 76 | puts "Creating folder structure" if opts.verbose 77 | FileUtils.mkdir("#{opts.output}") 78 | FileUtils.mkdir("#{opts.output}/Contents") 79 | FileUtils.mkdir("#{opts.output}/Contents/Chapters") 80 | FileUtils.mkdir("#{opts.output}/Contents/Resources") 81 | FileUtils.mkdir("#{opts.output}/Contents/Sources") 82 | FileUtils.mkdir("#{opts.output}/Contents/Chapters/#{opts.chapter}") 83 | FileUtils.mkdir("#{opts.output}/Contents/Chapters/#{opts.chapter}/Pages") 84 | FileUtils.mkdir("#{opts.output}/Contents/Chapters/#{opts.chapter}/Sources") 85 | end 86 | 87 | # Create the main manifest files 88 | def create_book_manifest(opts) 89 | identifier = "com.akosma.#{opts.output}" 90 | book_manifest = { 91 | 'Version' => '1.0', 92 | 'ContentIdentifier' => identifier, 93 | 'ContentVersion' => '1', 94 | 'DeploymentTarget' => 'ios10.0', 95 | 'Name' => opts.output, 96 | 'ImageReference' => 'icon.png', 97 | 'Chapters' => [ opts.chapter ] 98 | } 99 | book_manifest 100 | end 101 | 102 | def save_book_manifest(opts, book_manifest) 103 | book_manifest_path = "#{opts.output}/Contents/Manifest.plist" 104 | File.write(book_manifest_path, book_manifest.to_plist) 105 | book_manifest_path 106 | end 107 | 108 | # Create the chapter manifest 109 | def create_chapter_manifest(opts) 110 | chapter_manifest = { 111 | 'Name' => 'Chapter', 112 | 'Pages' => [] 113 | } 114 | chapter_manifest 115 | end 116 | 117 | # Create a slide manifest 118 | def create_slide_manifest(opts, title) 119 | slide_manifest = { 120 | 'Name' => title, 121 | 'LiveViewMode' => 'HiddenByDefault', 122 | 'LiveViewEdgeToEdge' => false 123 | } 124 | slide_manifest 125 | end 126 | 127 | def create_slides(opts, pages, chapter_manifest) 128 | pages.each_with_index do |page, index| 129 | title = page[:title] 130 | 131 | page_path = "#{opts.output}/Contents/Chapters/#{opts.chapter}/Pages/#{title}.playgroundpage" 132 | FileUtils.mkdir(page_path) 133 | 134 | slide_manifest = create_slide_manifest(opts, title) 135 | File.write("#{page_path}/Manifest.plist", slide_manifest.to_plist) 136 | 137 | File.open("#{page_path}/Contents.swift", 'w') do |file| 138 | # Here we break down the contents of the page by separating 139 | # codeblocks from other kind of objects. We basically create a 140 | # placeholder object where we flush all non-codeblock objects, and 141 | # we periodically flush that in the file, in Markdown format. 142 | # Codeblocks are flushed verbatim into the file. 143 | current = nil 144 | page[:doc].root.children.each do |element| 145 | if element.type == :codeblock 146 | # Flush the current object 147 | if current != nil 148 | file.write("/*:\n#{current.to_kramdown}\n*/") 149 | current = nil 150 | end 151 | # Write the contents of the codeblock literally 152 | file.write("\n\n#{element.value}\n") 153 | else 154 | current = Kramdown::Document.new('') if current == nil 155 | current.root.children << element 156 | end 157 | end 158 | if current != nil 159 | file.write("/*:\n#{current.to_kramdown}\n*/") 160 | end 161 | end 162 | 163 | # Add the new slide to the chapter manifest 164 | chapter_manifest['Pages'] << "#{title}.playgroundpage" 165 | end 166 | File.write("#{opts.output}/Contents/Chapters/#{opts.chapter}/Manifest.plist", chapter_manifest.to_plist) 167 | end 168 | 169 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMomentTests/XCTestManifests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | // swift test --generate-linuxmain 4 | 5 | extension DurationTests { 6 | static let __allTests = [ 7 | ("testCanAddAndSubstractDurations", testCanAddAndSubstractDurations), 8 | ("testCanCreateDurationsFromDoubles", testCanCreateDurationsFromDoubles), 9 | ("testCanCreateDurationsFromIntegers", testCanCreateDurationsFromIntegers), 10 | ("testCanGenerateMomentAgo", testCanGenerateMomentAgo), 11 | ("testDurationDescription", testDurationDescription), 12 | ("testDurationProperties", testDurationProperties), 13 | ("testSinceReturnsDuration", testSinceReturnsDuration), 14 | ] 15 | } 16 | 17 | extension ExtensionsTests { 18 | static let __allTests = [ 19 | ("testCanReturnDaysDuration", testCanReturnDaysDuration), 20 | ("testCanReturnDaysDurationAsDouble", testCanReturnDaysDurationAsDouble), 21 | ("testCanReturnHoursDuration", testCanReturnHoursDuration), 22 | ("testCanReturnHoursDurationAsDouble", testCanReturnHoursDurationAsDouble), 23 | ("testCanReturnMinutesDuration", testCanReturnMinutesDuration), 24 | ("testCanReturnMinutesDurationAsDouble", testCanReturnMinutesDurationAsDouble), 25 | ("testCanReturnMonthsDuration", testCanReturnMonthsDuration), 26 | ("testCanReturnMonthsDurationAsDouble", testCanReturnMonthsDurationAsDouble), 27 | ("testCanReturnQuartersDuration", testCanReturnQuartersDuration), 28 | ("testCanReturnQuartersDurationAsDouble", testCanReturnQuartersDurationAsDouble), 29 | ("testCanReturnSecondsDuration", testCanReturnSecondsDuration), 30 | ("testCanReturnSecondsDurationAsDouble", testCanReturnSecondsDurationAsDouble), 31 | ("testCanReturnWeeksDuration", testCanReturnWeeksDuration), 32 | ("testCanReturnWeeksDurationAsDouble", testCanReturnWeeksDurationAsDouble), 33 | ("testCanReturnYearsDuration", testCanReturnYearsDuration), 34 | ("testCanReturnYearsDurationAsDouble", testCanReturnYearsDurationAsDouble), 35 | ] 36 | } 37 | 38 | extension FromNowTests { 39 | static let __allTests = [ 40 | ("testFromNowEnglish", testFromNowEnglish), 41 | ("testFromNowHebrew", testFromNowHebrew), 42 | ] 43 | } 44 | 45 | extension MomentTests { 46 | static let __allTests = [ 47 | ("testAddingInt", testAddingInt), 48 | ("testAddingOtherValues", testAddingOtherValues), 49 | ("testAdditionAndSubstractionAreInverse", testAdditionAndSubstractionAreInverse), 50 | ("testAddSmallTimeSpans", testAddSmallTimeSpans), 51 | ("testCanCompareMoments", testCanCompareMoments), 52 | ("testCanCreateMomentsWithFiveComponents", testCanCreateMomentsWithFiveComponents), 53 | ("testCanCreateMomentsWithFourComponents", testCanCreateMomentsWithFourComponents), 54 | ("testCanCreateMomentsWithOneComponent", testCanCreateMomentsWithOneComponent), 55 | ("testCanCreateMomentsWithSixComponents", testCanCreateMomentsWithSixComponents), 56 | ("testCanCreateMomentsWithThreeComponents", testCanCreateMomentsWithThreeComponents), 57 | ("testCanCreateMomentsWithTwoComponents", testCanCreateMomentsWithTwoComponents), 58 | ("testCanCreateWeirdDateFromComponents", testCanCreateWeirdDateFromComponents), 59 | ("testCanGetParametersByGetter", testCanGetParametersByGetter), 60 | ("testCreateDateWithDictionary", testCreateDateWithDictionary), 61 | ("testDescriptions", testDescriptions), 62 | ("testDifferentSyntaxesToAddAndSubstract", testDifferentSyntaxesToAddAndSubstract), 63 | ("testDurationVSTimeUnitDoesNotMatterForDaysHoursMinutesSeconds", testDurationVSTimeUnitDoesNotMatterForDaysHoursMinutesSeconds), 64 | ("testEmptyArrayOfComponentsYieldsNilMoment", testEmptyArrayOfComponentsYieldsNilMoment), 65 | ("testEmptyDictionaryOfComponentsYieldsNilMoment", testEmptyDictionaryOfComponentsYieldsNilMoment), 66 | ("testEndOfDay", testEndOfDay), 67 | ("testEndOfMonth", testEndOfMonth), 68 | ("testEndOfWeek", testEndOfWeek), 69 | ("testEndOfYear", testEndOfYear), 70 | ("testEpoch", testEpoch), 71 | ("testEqualityIsCommutative", testEqualityIsCommutative), 72 | ("testFindMaximumMoment", testFindMaximumMoment), 73 | ("testFindMinimumMoment", testFindMinimumMoment), 74 | ("testFormatDates", testFormatDates), 75 | ("testFormatDatesWithLocale", testFormatDatesWithLocale), 76 | ("testFormatWithTimeZone", testFormatWithTimeZone), 77 | ("testFutureMoment", testFutureMoment), 78 | ("testGibberishIsInvalid", testGibberishIsInvalid), 79 | ("testLocaleSupport", testLocaleSupport), 80 | ("testMaximumWithoutParametersReturnsNil", testMaximumWithoutParametersReturnsNil), 81 | ("testMinimumWithoutParametersReturnsNil", testMinimumWithoutParametersReturnsNil), 82 | ("testMomentWithTimeZone", testMomentWithTimeZone), 83 | ("testPastMoment", testPastMoment), 84 | ("testPublicDate", testPublicDate), 85 | ("testPublicLocale", testPublicLocale), 86 | ("testPublicTimeZone", testPublicTimeZone), 87 | ("testStartOfDay", testStartOfDay), 88 | ("testStartOfHour", testStartOfHour), 89 | ("testStartOfMinute", testStartOfMinute), 90 | ("testStartOfMonth", testStartOfMonth), 91 | ("testStartOfSecond", testStartOfSecond), 92 | ("testStartOfWeek", testStartOfWeek), 93 | ("testStartOfYear", testStartOfYear), 94 | ("testSubstractSmallTimeSpans", testSubstractSmallTimeSpans), 95 | ("testTheMomentIsNow", testTheMomentIsNow), 96 | ("testTimeZoneChangeAdd", testTimeZoneChangeAdd), 97 | ("testTimeZoneChangeEndOf", testTimeZoneChangeEndOf), 98 | ("testTimeZoneChangesPreserveMomentInGMT", testTimeZoneChangesPreserveMomentInGMT), 99 | ("testTimeZoneChangeStartOf", testTimeZoneChangeStartOf), 100 | ("testTimeZoneChangeSubtract", testTimeZoneChangeSubtract), 101 | ("testTimeZoneStartOfDay", testTimeZoneStartOfDay), 102 | ("testTransformTimeZone", testTransformTimeZone), 103 | ("testUsingWrongParameterNameYieldsNil", testUsingWrongParameterNameYieldsNil), 104 | ("testUTCMomentSupport", testUTCMomentSupport), 105 | ("testWrongArrayReturnsNil", testWrongArrayReturnsNil), 106 | ("testWrongFormatParametersReturnNil", testWrongFormatParametersReturnNil), 107 | ("testWrongUnitInAddReturnsSelf", testWrongUnitInAddReturnsSelf), 108 | ("testWrongUnitInEndOfReturnsSelf", testWrongUnitInEndOfReturnsSelf), 109 | ("testWrongUnitInStartOfReturnsSelf", testWrongUnitInStartOfReturnsSelf), 110 | ("testWrongUnitInSubstractReturnsSelf", testWrongUnitInSubstractReturnsSelf), 111 | ] 112 | } 113 | 114 | #if !os(macOS) 115 | public func __allTests() -> [XCTestCaseEntry] { 116 | return [ 117 | testCase(DurationTests.__allTests), 118 | testCase(ExtensionsTests.__allTests), 119 | testCase(FromNowTests.__allTests), 120 | testCase(MomentTests.__allTests), 121 | ] 122 | } 123 | #endif 124 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMomentTests/ExtensionsTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ExtensionsTests.swift 3 | // SwiftMoment 4 | // 5 | // Created by akihiro0228 on 2016/01/04. 6 | // Copyright (c) 2016 Adrian Kosmaczewski. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import XCTest 11 | import SwiftMoment 12 | 13 | class ExtensionsTests: XCTestCase { 14 | 15 | override func setUp() { 16 | super.setUp() 17 | } 18 | 19 | override func tearDown() { 20 | super.tearDown() 21 | } 22 | 23 | func testCanReturnSecondsDuration() { 24 | XCTAssertEqual(1.seconds, Duration(value: 1 * 1), 25 | "The Duration instance by one seconds is returned") 26 | XCTAssertEqual(2.seconds, Duration(value: 1 * 2), 27 | "The Duration instance by two seconds is returned") 28 | XCTAssertEqual(3.seconds, Duration(value: 1 * 3), 29 | "The Duration instance by three seconds is returned") 30 | } 31 | 32 | func testCanReturnMinutesDuration() { 33 | XCTAssertEqual(1.minutes, Duration(value: 60 * 1), 34 | "The Duration instance by one minutes is returned") 35 | XCTAssertEqual(2.minutes, Duration(value: 60 * 2), 36 | "The Duration instance by two minutes is returned") 37 | XCTAssertEqual(3.minutes, Duration(value: 60 * 3), 38 | "The Duration instance by three minutes is returned") 39 | } 40 | 41 | func testCanReturnHoursDuration() { 42 | XCTAssertEqual(1.hours, Duration(value: 3600 * 1), 43 | "The Duration instance by one hours is returned") 44 | XCTAssertEqual(2.hours, Duration(value: 3600 * 2), 45 | "The Duration instance by two hours is returned") 46 | XCTAssertEqual(3.hours, Duration(value: 3600 * 3), 47 | "The Duration instance by three hours is returned") 48 | } 49 | 50 | func testCanReturnDaysDuration() { 51 | XCTAssertEqual(1.days, Duration(value: 86400 * 1), 52 | "The Duration instance by one days is returned") 53 | XCTAssertEqual(2.days, Duration(value: 86400 * 2), 54 | "The Duration instance by two days is returned") 55 | XCTAssertEqual(3.days, Duration(value: 86400 * 3), 56 | "The Duration instance by three days is returned") 57 | } 58 | 59 | func testCanReturnWeeksDuration() { 60 | XCTAssertEqual(1.weeks, Duration(value: 604800 * 1), 61 | "The Duration instance by one week is returned") 62 | XCTAssertEqual(2.weeks, Duration(value: 604800 * 2), 63 | "The Duration instance by two weeks is returned") 64 | XCTAssertEqual(3.weeks, Duration(value: 604800 * 3), 65 | "The Duration instance by three weeks is returned") 66 | } 67 | 68 | func testCanReturnMonthsDuration() { 69 | XCTAssertEqual(1.months, Duration(value: 2592000 * 1), 70 | "The Duration instance by one months is returned") 71 | XCTAssertEqual(2.months, Duration(value: 2592000 * 2), 72 | "The Duration instance by two months is returned") 73 | XCTAssertEqual(3.months, Duration(value: 2592000 * 3), 74 | "The Duration instance by three months is returned") 75 | } 76 | 77 | func testCanReturnQuartersDuration() { 78 | XCTAssertEqual(1.quarters, Duration(value: 7776000 * 1), 79 | "The Duration instance by one quarters is returned") 80 | XCTAssertEqual(2.quarters, Duration(value: 7776000 * 2), 81 | "The Duration instance by two quarters is returned") 82 | XCTAssertEqual(3.quarters, Duration(value: 7776000 * 3), 83 | "The Duration instance by three quarters is returned") 84 | } 85 | 86 | func testCanReturnYearsDuration() { 87 | XCTAssertEqual(1.years, Duration(value: 31536000 * 1), 88 | "The Duration instance by one years is returned") 89 | XCTAssertEqual(2.years, Duration(value: 31536000 * 2), 90 | "The Duration instance by two years is returned") 91 | XCTAssertEqual(3.years, Duration(value: 31536000 * 3), 92 | "The Duration instance by three years is returned") 93 | } 94 | 95 | func testCanReturnSecondsDurationAsDouble() { 96 | XCTAssertEqual(1.5.seconds, Duration(value: 1 * 1.5), 97 | "The Duration instance by 1.5 seconds is returned") 98 | XCTAssertEqual(2.5.seconds, Duration(value: 1 * 2.5), 99 | "The Duration instance by 2.5 seconds is returned") 100 | XCTAssertEqual(3.5.seconds, Duration(value: 1 * 3.5), 101 | "The Duration instance by 3.5 seconds is returned") 102 | } 103 | 104 | func testCanReturnMinutesDurationAsDouble() { 105 | XCTAssertEqual(1.5.minutes, Duration(value: 60 * 1.5), 106 | "The Duration instance by 1.5 minutes is returned") 107 | XCTAssertEqual(2.5.minutes, Duration(value: 60 * 2.5), 108 | "The Duration instance by 2.5 minutes is returned") 109 | XCTAssertEqual(3.5.minutes, Duration(value: 60 * 3.5), 110 | "The Duration instance by 3.5 minutes is returned") 111 | } 112 | 113 | func testCanReturnHoursDurationAsDouble() { 114 | XCTAssertEqual(1.5.hours, Duration(value: 3600 * 1.5), 115 | "The Duration instance by 1.5 hours is returned") 116 | XCTAssertEqual(2.5.hours, Duration(value: 3600 * 2.5), 117 | "The Duration instance by 2.5 hours is returned") 118 | XCTAssertEqual(3.5.hours, Duration(value: 3600 * 3.5), 119 | "The Duration instance by 3.5 hours is returned") 120 | } 121 | 122 | func testCanReturnDaysDurationAsDouble() { 123 | XCTAssertEqual(1.5.days, Duration(value: 86400 * 1.5), 124 | "The Duration instance by 1.5 days is returned") 125 | XCTAssertEqual(2.5.days, Duration(value: 86400 * 2.5), 126 | "The Duration instance by 2.5 days is returned") 127 | XCTAssertEqual(3.5.days, Duration(value: 86400 * 3.5), 128 | "The Duration instance by 3.5 days is returned") 129 | } 130 | 131 | func testCanReturnWeeksDurationAsDouble() { 132 | XCTAssertEqual(1.5.weeks, Duration(value: 604800 * 1.5), 133 | "The Duration instance by 1.5 week is returned") 134 | XCTAssertEqual(2.5.weeks, Duration(value: 604800 * 2.5), 135 | "The Duration instance by 2.5 weeks is returned") 136 | XCTAssertEqual(3.5.weeks, Duration(value: 604800 * 3.5), 137 | "The Duration instance by 3.5 weeks is returned") 138 | } 139 | 140 | func testCanReturnMonthsDurationAsDouble() { 141 | XCTAssertEqual(1.5.months, Duration(value: 2592000 * 1.5), 142 | "The Duration instance by 1.5 months is returned") 143 | XCTAssertEqual(2.5.months, Duration(value: 2592000 * 2.5), 144 | "The Duration instance by 2.5 months is returned") 145 | XCTAssertEqual(3.5.months, Duration(value: 2592000 * 3.5), 146 | "The Duration instance by 3.5 months is returned") 147 | } 148 | 149 | func testCanReturnQuartersDurationAsDouble() { 150 | XCTAssertEqual(1.5.quarters, Duration(value: 7776000 * 1.5), 151 | "The Duration instance by 1.5 quarters is returned") 152 | XCTAssertEqual(2.5.quarters, Duration(value: 7776000 * 2.5), 153 | "The Duration instance by 2.5 quarters is returned") 154 | XCTAssertEqual(3.5.quarters, Duration(value: 7776000 * 3.5), 155 | "The Duration instance by 3.5 quarters is returned") 156 | } 157 | 158 | func testCanReturnYearsDurationAsDouble() { 159 | XCTAssertEqual(1.5.years, Duration(value: 31536000 * 1.5), 160 | "The Duration instance by 1.5 years is returned") 161 | XCTAssertEqual(2.5.years, Duration(value: 31536000 * 2.5), 162 | "The Duration instance by 2.5 years is returned") 163 | XCTAssertEqual(3.5.years, Duration(value: 31536000 * 3.5), 164 | "The Duration instance by 3.5 years is returned") 165 | } 166 | 167 | } 168 | -------------------------------------------------------------------------------- /Book/SwiftMoment.md: -------------------------------------------------------------------------------- 1 | # SwiftMoment 2 | 3 | This framework is inspired by [Moment.js](http://momentjs.com). Its 4 | objectives are the following: 5 | 6 | - Simplify the manipulation and readability of date and interval values. 7 | - Provide help when parsing dates from various string representations. 8 | - Simplifying the formatting of date information into strings. 9 | - Streamlining getting date components (day, month, etc.) from dates and 10 | time intervals. 11 | 12 | Important: This framework supports iOS 9+, macOS 10.11+, tvOS 9+, watchOS 2+, Xcode 8 and Swift 3. 13 | 14 | Please pay attention to the following API difference with 15 | [Moment.js](http://momentjs.com) 16 | 17 | - Format strings `DD` and `dd` do not yield the same results. 18 | 19 | --- 20 | 21 | # Installation 22 | 23 | You can include SwiftMoment in your project in three different ways: 24 | 25 | 1. You can drag and drop the library files, including 26 | `MomentFromNow.bundle` in your own project. Swift Moment does not 27 | have any other dependencies than Foundation (actually this is the 28 | method we have used in this Playground Book!) 29 | 2. Use [CocoaPods]:https://cocoapods.org 30 | 3. Use [Carthage]:http://github.com/Carthage/Carthage 31 | 32 | If you are using CocoaPods, just add this line to your Podfile: 33 | 34 | ``` 35 | pod 'SwiftMoment' 36 | ``` 37 | 38 | It is strongly recommended to add a version number to your podfile: 39 | 40 | ``` 41 | pod 'SwiftMoment', '~> 0.7' 42 | ``` 43 | 44 | (Version 0.7 is the latest version available at the time of this 45 | writing.) 46 | 47 | Once you have installed SwiftMoment, we can move to the next chapter and 48 | learn how to use it. 49 | 50 | ## Mac OS X Notes 51 | 52 | - Drag the created .framework file into the Xcode Project, be sure to 53 | tick 'Copy Files to Directory' 54 | - In the containing applications target, add a new 'Copy File Build 55 | Phase' 56 | - Set the 'Destination' to 'Frameworks' 57 | - Drag in the created .framework 58 | 59 | --- 60 | 61 | # Using SwiftMoment 62 | 63 | The two most important components of SwiftMoment are the `Moment` and 64 | `Duration` structures. `Moment` wraps an `NSDate` instance, while 65 | `Duration` wraps an `NSTimeInterval` value. 66 | 67 | Both `Moment` and `Duration` comply with the `Comparable` protocols, and 68 | include all the required operators. In addition, `Moment` instances can 69 | be subtracted from one another (which yields a `Duration`) and 70 | `Duration` instances can be added to `Moments` to create new moments. 71 | 72 | `Moments` and `Durations` are both immutable. 73 | 74 | ## Creating Moments 75 | 76 | To use this library, just `import SwiftMoment` in your application, then 77 | call the `moment()` function: 78 | 79 | let now = moment() 80 | 81 | This will create a new `Moment` ready to be used, representing the 82 | current date. 83 | 84 | ### Creating Moments with Strings 85 | 86 | You can also create moments based on dates both in the future and the 87 | past: 88 | 89 | let yesterday = moment("2015-01-19") 90 | 91 | SwiftMoment supports a wide array of valid string formats off-the-box: 92 | 93 | // Famous battles of the 19th century: 94 | let meierskappel = moment("November 23, 1847")! 95 | let gettysburg = moment("Jul/01/1863")! 96 | let pavon = moment("1861-09-17T10:30:00GMT-4")! 97 | 98 | This is the full list of default formats. 99 | 100 | - "yyyy-MM-dd'T'HH:mm:ssZZZZZ" (ISO) 101 | - "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'" 102 | - "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'SSS'Z'" 103 | - "yyyy-MM-dd'T'HH:mm:ss.SSSZ" 104 | - "yyyy-MM-dd" 105 | - "h:mm:ss A" 106 | - "h:mm A" 107 | - "MM/dd/yyyy" 108 | - "MMMM d, yyyy" 109 | - "MMMM d, yyyy LT" 110 | - "dddd, MMMM D, yyyy LT" 111 | - "yyyyyy-MM-dd" 112 | - "yyyy-MM-dd" 113 | - "GGGG-[W]WW-E" 114 | - "GGGG-[W]WW" 115 | - "yyyy-ddd" 116 | - "HH:mm:ss.SSSS" 117 | - "HH:mm:ss" 118 | - "HH:mm" 119 | - "HH" 120 | 121 | Since SwiftMoment wraps the standard date formatting functionality of 122 | the Foundation framework, the format string uses the format patterns 123 | from the [Unicode Technical Standard #35](http://www.unicode.org/reports/tr35/tr35-31/tr35-dates.html#Date_Format_Patterns). 124 | 125 | Of course, if your format does not happen to be supported off-the-box, 126 | you can pass it as parameter when creating your moment; this allows you 127 | to parse and use dates in the most weird formats. 128 | 129 | let data = "Tue 1973/4--September 12:30 GMT-03:00" 130 | let format = "EE yyyy/dd--MMMM HH:mm ZZZZ" 131 | let birthday = moment(data, dateFormat: format)! 132 | 133 | ### Creating Moments with Arrays and Dictionaries 134 | 135 | You can also specify the date components manually, in which case the 136 | elements are read in a particular order: year, month, day, hour, minute 137 | and second. Missing parameters are automatically initialized to zero: 138 | 139 | let today = moment([2015, 01, 19, 20, 45, 34]) 140 | let todayAtMidnight = moment([2015, 01, 19]) 141 | 142 | Or using a dictionary: 143 | 144 | let withDict = moment(["year": 2015, 145 | "second": 34, 146 | "minute": 45, 147 | "month": 01, 148 | "hour": 20, 149 | "day": 19, 150 | "ignored_whatever": 25346436 151 | ]) 152 | 153 | When using a `[String: Int]` dictionary, the order of the keys does not 154 | matter. Moreover, only the keys above are taken into account, and any 155 | other information is ignored. 156 | 157 | If you pass an empty array or dictionary, you get an `Optional` 158 | value that evaluates to `nil`. 159 | 160 | ### Creating Moments with Other Parameters 161 | 162 | SwiftMoment integrates nicely with any existing Swift code that may 163 | already be using `Date`, `TimeInterval` or even integer representing 164 | milliseconds: 165 | 166 | import Foundation 167 | 168 | let date = Date() 169 | let withDate = moment(date) 170 | let systemMilliseconds = moment(25433465) 171 | let hundredSecondsAfterEpoch = moment(TimeInterval(100)) 172 | 173 | If you need to copy a Moment into another, just pass it to the 174 | `moment()` function: 175 | 176 | let original = moment() 177 | let copy = moment(original) 178 | 179 | ### Convenience Functions 180 | 181 | SwiftMoment includes other useful functions to manipulate time and date 182 | information in your applications: 183 | 184 | // Past and future 185 | let middle = moment() 186 | let p = past() 187 | let f = future() 188 | 189 | // Maximum and minimum 190 | let max = maximum(f, middle, p) // f, of course 191 | let min = minimum(p, f, middle) // p, of course 192 | 193 | ### Manipulating Moments 194 | 195 | However you create a Moment, you can inspect it and get all the 196 | information you need. 197 | 198 | let obj = moment() 199 | 200 | // returns the wrapped values inside 201 | obj.date 202 | obj.timeZone 203 | obj.locale 204 | 205 | // show the different parts of the moment 206 | obj.second 207 | obj.minute 208 | obj.hour 209 | obj.day 210 | obj.weekday 211 | obj.weekdayName 212 | obj.monthName 213 | obj.month 214 | obj.quarter 215 | obj.year 216 | 217 | // you can alternatively use the get() methods: 218 | obj.get(.days) 219 | obj.get("m") // returns the minutes 220 | 221 | The `get()` method uses the `TimeUnit` enumeration or its string value, 222 | which is another component of SwiftMoment. You can use the following 223 | string values instead of the enumeration values, if you prefer: 224 | 225 | - `.years` = "y" 226 | - `.quarters` = "Q" 227 | - `.months` = "M" 228 | - `.weeks` = "w" 229 | - `.days` = "d" 230 | - `.hours` = "H" 231 | - `.minutes` = "m" 232 | - `.seconds` = "s" 233 | 234 | Of course, the version of `get()` that takes a string will return `nil` 235 | if you provide an invalid value. 236 | 237 | ## Durations 238 | 239 | There is also an extension to the `Int` type in Swift, used to create 240 | `Duration` values directly from an integer value: 241 | 242 | let duration = 5.hours + 56.minutes 243 | 244 | --- 245 | 246 | # Contributor Guidelines 247 | 248 | So you want to help us making a better SwiftMoment? Thanks! For the sake 249 | of a productive collaboration, please pay attention to the following 250 | collaboration guidelines: 251 | 252 | ## Pull Requests > Issues 253 | 254 | Whenever possible, try to provide us with [pull 255 | requests](https://help.github.com/articles/creating-a-pull-request/) 256 | instead of simply creating an issue. Pull requests help us move forward 257 | faster, and we will be glad to review and eventually include it in the 258 | master branch. 259 | 260 | ## Issues 261 | 262 | If you open an issue, make sure to include a complete description. 263 | Follow the template that appears on the form, including as much 264 | information as possible. You should include code snippets that helps us 265 | reproduce the error. Saying "it does not work" without further context 266 | does not help anybody. 267 | 268 | ## Pull Requests 269 | 270 | If you create a pull request, please be aware that we only accept pull 271 | requests that include unit tests for your changes. **We do not accept 272 | pull requests without the appropriate unit tests** unless they are just 273 | grammar, cosmetic, documentation or typographical corrections. 274 | 275 | Before sending a pull request, make sure that: 276 | 277 | 1. Your code compiles without warnings of any kind. 278 | 2. Your code runs without runtime warnings. 279 | 3. You have checked your code with either 280 | [SwiftLint](https://github.com/realm/SwiftLint) or 281 | [Tailor](https://tailor.sh) and you have removed any warnings shown 282 | by either of these tools. 283 | 4. You have included unit tests for your feature, if required. 284 | 5. All previous unit tests pass. 285 | 6. You have included and/or updated API documentation in the public 286 | methods, structs and classes that are referenced by your pull 287 | request. 288 | 289 | ## Behaviour 290 | 291 | We want SwiftMoment to be an inclusive project. Please be kind and 292 | helpful in your comments. In case of doubt, ask questions. Be honest and 293 | humble. May SwiftMoment be a better place after you have been here :) 294 | 295 | --- 296 | 297 | # Authors 298 | 299 | ## Core Committers 300 | 301 | - [Adrian Kosmaczewski](https://github.com/akosma) 302 | - [Florent Pillet](https://github.com/fpillet) 303 | - [Madhava Jay](https://github.com/madhavajay) 304 | 305 | ## Contributors 306 | 307 | This is the people that have helped making SwiftMoment with pull 308 | requests, bug submissions, etc since 2015: 309 | 310 | - [박현재](https://github.com/hyeonjae) 311 | - [akihiro0228](https://github.com/akihiro0228) 312 | - [Aaron Brager](https://github.com/getaaron) 313 | - [Adriano Goncalves](https://github.com/amg1976) 314 | - [Anders Klenke](https://github.com/andersklenke) 315 | - [Andrew Barba](https://github.com/AndrewBarba) 316 | - [Andrew Branch](https://github.com/andrewbranch) 317 | - [Burak Akkaş](https://github.com/javasch) 318 | - [Chris Sloey](https://github.com/chrissloey) 319 | - [Daniel Cestari](https://github.com/dcestari) 320 | - [David Harris](https://github.com/toadzky) 321 | - [Eric Fang](https://github.com/fjhixiuxiu) 322 | - [Fabio Felici](https://github.com/fabfelici) 323 | - [Hadar Landao](https://github.com/hlandao) 324 | - [Jake Johnson](https://github.com/johnsonjake) 325 | - [karupanenura](https://github.com/karupanerura) 326 | - [Ken Goldfarb](https://github.com/kengoldfarb) 327 | - [Laurin Brandner](https://github.com/larcus94) 328 | - [Masaya Yashiro](https://github.com/yashims) 329 | - [Mihyaeru](https://github.com/mihyaeru21) 330 | - [Narayan Sainaney](https://github.com/nsainaney) 331 | - [Nate Armstrong](https://github.com/n8armstrong) 332 | - [Neil](https://github.com/AsFarA) 333 | - [PG Herveou](https://github.com/pgherveou) 334 | - [Pine Mizune](https://github.com/pine613) 335 | - [Robert La Ferla](https://github.com/rlaferla) 336 | - [Ryan Maxwell](https://github.com/ryanmaxwell) 337 | - [Ryo Yamada](https://github.com/Liooo) 338 | - [Tatiana Magdalena](https://github.com/tatimagdalena) 339 | - [Tomáš Slíž](https://github.com/tomassliz) 340 | 341 | ## Special Thanks 342 | 343 | A big shoutout to [Dave Verwer](https://twitter.com/daveverwer) who 344 | kindly featured SwiftMoment in [iOS Dev Weekly issue 345 | 186](http://iosdevweekly.com/issues/186), to [Natasha 346 | Murashev](http://natashatherobot.com) who also featured SwiftMoment in 347 | her newsletter, and to [Swift Sandbox](http://swiftsandbox.io) who 348 | featured SwiftMoment in [issue 36](http://swiftsandbox.io/issues/36?#start)! 349 | Please make sure to subscribe to all of these newsletters! 350 | 351 | Also thanks to [Matteo Crippa](https://github.com/matteocrippa) and 352 | [dkhamsing](https://github.com/dkhamsing) for featuring SwiftMoment in 353 | the [awesome swift](https://github.com/matteocrippa/awesome-swift) list! 354 | 355 | --- 356 | 357 | # License 358 | 359 | Copyright (c) 2015, Adrian Kosmaczewski 360 | All rights reserved. 361 | 362 | Redistribution and use in source and binary forms, with or without modification, 363 | are permitted provided that the following conditions are met: 364 | 365 | 1. Redistributions of source code must retain the above copyright notice, this 366 | list of conditions and the following disclaimer. 367 | 368 | 2. Redistributions in binary form must reproduce the above copyright notice, 369 | this list of conditions and the following disclaimer in the documentation 370 | and/or other materials provided with the distribution. 371 | 372 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 373 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 374 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 375 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 376 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 377 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 378 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 379 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 380 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 381 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 382 | 383 | --- 384 | 385 | # Credits 386 | 387 | This book has been generated using 388 | [PlaygroundBookGenerator](https://github.com/akosma/PlaygroundBookGenerator) 389 | by Adrian Kosmaczewski. 390 | 391 | -------------------------------------------------------------------------------- /SwiftMoment/SwiftMomentTests/MomentTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftMomentTests.swift 3 | // SwiftMomentTests 4 | // 5 | // Created by Adrian on 19/01/15. 6 | // Copyright (c) 2015 Adrian Kosmaczewski. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import XCTest 11 | import SwiftMoment 12 | 13 | class MomentTests: XCTestCase { 14 | 15 | override func setUp() { 16 | super.setUp() 17 | } 18 | 19 | override func tearDown() { 20 | super.tearDown() 21 | } 22 | 23 | func testTheMomentIsNow() { 24 | let today = moment() 25 | 26 | let date = Date() 27 | var cal = Calendar.current 28 | cal.timeZone = TimeZone.current 29 | let params: Set = [.year, .month, .day, .hour, .minute, .second, .weekday, 30 | .weekdayOrdinal, .weekOfYear, .quarter] 31 | let components = cal.dateComponents(params, from: date) 32 | 33 | XCTAssertEqual(today.year, components.year, "The moment contains the current year") 34 | XCTAssertEqual(today.month, components.month, "The moment contains the current month") 35 | XCTAssertEqual(today.day, components.day, "The moment contains the current day") 36 | XCTAssertEqual(today.hour, components.hour, "The moment contains the current hour") 37 | XCTAssertEqual(today.minute, components.minute, "The moment contains the current minute") 38 | XCTAssertEqual(today.second, components.second, "The moment contains the current second") 39 | XCTAssertEqual(today.weekday, components.weekday, "The moment contains the current weekday") 40 | XCTAssertEqual(today.weekOfYear, components.weekOfYear, 41 | "The moment contains the current week of year") 42 | XCTAssertEqual(today.weekdayOrdinal, components.weekdayOrdinal, 43 | "The moment contains the current number of the week day") 44 | XCTAssertEqual(today.quarter, components.quarter, "The moment contains the current quarter") 45 | 46 | let formatter = DateFormatter() 47 | formatter.dateFormat = "EEEE" 48 | let weekdayName = formatter.string(from: date) 49 | 50 | XCTAssertEqual(today.weekdayName, weekdayName, "The moment contains the current week day") 51 | } 52 | 53 | func testCanCreateMomentsWithSixComponents() { 54 | let obj = moment([2015, 01, 19, 20, 45, 34])! 55 | XCTAssertEqual(obj.year, 2015, "The year should match") 56 | XCTAssertEqual(obj.month, 01, "The month should match") 57 | XCTAssertEqual(obj.day, 19, "The day should match") 58 | XCTAssertEqual(obj.hour, 20, "The hour should match") 59 | XCTAssertEqual(obj.minute, 45, "The minute should match") 60 | XCTAssertEqual(obj.second, 34, "The second should match") 61 | } 62 | 63 | func testCanCreateMomentsWithFiveComponents() { 64 | let obj = moment([2015, 01, 19, 20, 45])! 65 | XCTAssertEqual(obj.year, 2015, "The year should match") 66 | XCTAssertEqual(obj.month, 01, "The month should match") 67 | XCTAssertEqual(obj.day, 19, "The day should match") 68 | XCTAssertEqual(obj.hour, 20, "The hour should match") 69 | XCTAssertEqual(obj.minute, 45, "The minute should match") 70 | XCTAssertEqual(obj.second, 0, "The second should be zero") 71 | } 72 | 73 | func testCanCreateMomentsWithFourComponents() { 74 | let obj = moment([2015, 01, 19, 20])! 75 | XCTAssertEqual(obj.year, 2015, "The year should match") 76 | XCTAssertEqual(obj.month, 01, "The month should match") 77 | XCTAssertEqual(obj.day, 19, "The day should match") 78 | XCTAssertEqual(obj.hour, 20, "The hour should match") 79 | XCTAssertEqual(obj.minute, 0, "The minute should be zero") 80 | XCTAssertEqual(obj.second, 0, "The second should be zero") 81 | } 82 | 83 | func testCanCreateMomentsWithThreeComponents() { 84 | let obj = moment([2015, 01, 19])! 85 | XCTAssertEqual(obj.year, 2015, "The year should match") 86 | XCTAssertEqual(obj.month, 01, "The month should match") 87 | XCTAssertEqual(obj.day, 19, "The day should match") 88 | XCTAssertEqual(obj.hour, 0, "The hour should be zero") 89 | XCTAssertEqual(obj.minute, 0, "The minute should be zero") 90 | XCTAssertEqual(obj.second, 0, "The second should be zero") 91 | } 92 | 93 | func testCanCreateMomentsWithTwoComponents() { 94 | let obj = moment([2015, 01])! 95 | XCTAssertEqual(obj.year, 2015, "The year should match") 96 | XCTAssertEqual(obj.month, 01, "The month should match") 97 | XCTAssertEqual(obj.day, 1, "The day should be one") 98 | XCTAssertEqual(obj.hour, 0, "The hour should be zero") 99 | XCTAssertEqual(obj.minute, 0, "The minute should be zero") 100 | XCTAssertEqual(obj.second, 0, "The second should be zero") 101 | } 102 | 103 | func testCanCreateMomentsWithOneComponent() { 104 | let obj = moment([2015])! 105 | XCTAssertEqual(obj.year, 2015, "The year should match") 106 | XCTAssertEqual(obj.month, 1, "The month should be January") 107 | XCTAssertEqual(obj.day, 1, "The day should be the first") 108 | XCTAssertEqual(obj.hour, 0, "The hour should be zero") 109 | XCTAssertEqual(obj.minute, 0, "The minute should be zero") 110 | XCTAssertEqual(obj.second, 0, "The second should be zero") 111 | } 112 | 113 | func testCanCreateMomentsWithISO8601WithMilliseconds() { 114 | let timeZone = TimeZone(abbreviation: "GMT+03")! 115 | let stringWithMilliseconds = "2017-11-28T13:25:43.123Z" 116 | let obj = moment(stringWithMilliseconds, timeZone:timeZone)! 117 | XCTAssertEqual(obj.year, 2017, "The year should match") 118 | XCTAssertEqual(obj.month, 11, "The month should match") 119 | XCTAssertEqual(obj.day, 28, "The day should match") 120 | XCTAssertEqual(obj.hour, 16, "The hour should be 16") 121 | XCTAssertEqual(obj.minute, 25, "The minute should match") 122 | XCTAssertEqual(obj.second, 43, "The second should match") 123 | } 124 | 125 | func testCanCreateWeirdDateFromComponents() { 126 | let timeZone = TimeZone(abbreviation: "GMT+01")! 127 | let obj = moment([-2015445, 76, -46, 876, 234565, -999], timeZone: timeZone)! 128 | XCTAssertEqual(obj.format(), "2015440-02-13 12:57:11 GMT+01:00", "The date is weird...!") 129 | } 130 | 131 | func testEmptyArrayOfComponentsYieldsNilMoment() { 132 | let obj = moment([]) 133 | XCTAssert(obj == nil, "This should yield a nil moment object") 134 | } 135 | 136 | func testCreateDateWithDictionary() { 137 | let obj = moment(["year": 2015, 138 | "second": 34, 139 | "month": 01, 140 | "minute": 45, 141 | "day": 19, 142 | "hour": 20, 143 | "ignoredKey": 2342432])! 144 | XCTAssertEqual(obj.year, 2015, "The year should match") 145 | XCTAssertEqual(obj.month, 01, "The month should match") 146 | XCTAssertEqual(obj.day, 19, "The day should match") 147 | XCTAssertEqual(obj.hour, 20, "The hour should match") 148 | XCTAssertEqual(obj.minute, 45, "The minute should match") 149 | XCTAssertEqual(obj.second, 34, "The second should match") 150 | } 151 | 152 | func testEmptyDictionaryOfComponentsYieldsNilMoment() { 153 | let obj = moment(["whatever": 453]) 154 | XCTAssert(obj == nil, "This should yield a nil moment object") 155 | } 156 | 157 | func testGibberishIsInvalid() { 158 | let gibberish = moment("whatever") 159 | XCTAssert(gibberish == nil, "Gibberish is invalid") 160 | } 161 | 162 | func testCanCompareMoments() { 163 | let today = moment() 164 | let today2 = moment(Date()) 165 | let epoch = moment(0) 166 | 167 | let copy = moment(epoch) 168 | let ninetyFive = moment("1995-12-25")! 169 | XCTAssertNotEqual(ninetyFive, epoch, "The epoch did not happen in 1995") 170 | XCTAssertGreaterThan(today, ninetyFive, "Today happens after 1995") 171 | XCTAssertLessThan(ninetyFive, today, "Today does not happen before 1995") 172 | XCTAssert(today ~= today2, "Separated by some milliseconds") 173 | XCTAssertEqual(epoch, copy, "Copies are exactly equal") 174 | 175 | let similar = ninetyFive + 30.seconds 176 | XCTAssert(ninetyFive ~= similar, "Separated by 30 seconds") 177 | } 178 | 179 | func testEqualityIsCommutative() { 180 | let today = moment() 181 | let copy = moment(today) 182 | XCTAssertEqual(today, copy, "Equality is commutative") 183 | XCTAssertEqual(copy, today, "Equality is commutative") 184 | } 185 | 186 | func testDifferentSyntaxesToAddAndSubstract() { 187 | // month durations always add 30 days 188 | let one = moment([2015, 7, 29, 0, 0])! 189 | let exactlyThirtyDays = moment([2015, 8, 28, 0, 0])! 190 | XCTAssertEqual(exactlyThirtyDays, one.add(1.months), "Duration adds exactly 30 days") 191 | XCTAssertEqual(30.days, exactlyThirtyDays - one, 192 | "exactly_thirty_days is a difference of 30 days") 193 | XCTAssertEqual(one, exactlyThirtyDays.subtract(1.0, .months), 194 | "Subtracting back to one is okay") 195 | 196 | // adding by a TimeUnit.Month jumps 1 month (not necessarily 30 days) 197 | let two = moment([2015, 7, 29, 0, 0])! 198 | let exactlyOneMonth = moment([2015, 8, 28, 0, 0])! 199 | XCTAssertEqual(exactlyOneMonth, two.add(1.0, .months), "Time unit adds exactly one month") 200 | XCTAssertEqual(30.days, exactlyOneMonth - two, 201 | "exactly_on_month is a difference of 30 days") 202 | XCTAssertEqual(two, exactlyOneMonth.subtract(1, .months), 203 | "Subtracting back to two is okay") 204 | 205 | // use Duration to always add/subtract 365 days for years, 206 | // otherwise, use TimeUnit.Year 207 | let allYears365 = moment().add(5.years) 208 | let considerLeapYears = moment().add(5, .years) 209 | let considerLeapYears2 = moment().add(5.0, .years) 210 | XCTAssertTrue(allYears365 ~= considerLeapYears) 211 | XCTAssertTrue(considerLeapYears ~= considerLeapYears2) 212 | } 213 | 214 | func testAddingOtherValues() { 215 | let now = moment() 216 | var future = now.add(1.2, .minutes) 217 | var nowagain = future.subtract(1.2, .minutes) 218 | XCTAssertEqual(now, nowagain) 219 | 220 | future = now.add(1.3, .hours) 221 | nowagain = future.subtract(1.3, .hours) 222 | XCTAssertEqual(now, nowagain) 223 | 224 | future = now.add(1.3, .days) 225 | nowagain = future.subtract(1.3, .days) 226 | XCTAssertEqual(now, nowagain) 227 | 228 | future = now.add(1.3, .weeks) 229 | nowagain = future.subtract(1.3, .weeks) 230 | XCTAssertEqual(now, nowagain) 231 | 232 | future = now.add(1.3, .quarters) 233 | nowagain = future.subtract(1.3, .quarters) 234 | XCTAssertEqual(now, nowagain) 235 | } 236 | 237 | func testDurationVSTimeUnitDoesNotMatterForDaysHoursMinutesSeconds() { 238 | let today = moment() 239 | let first = moment(today).add(50.days) 240 | let second = moment(today).add(50, .days) 241 | XCTAssertEqual(first, second, "Syntax does not matter when adding days") 242 | XCTAssertEqual(first.subtract(40, .days), second.subtract(40.days), 243 | "Syntax does not matter when subtracting days") 244 | } 245 | 246 | func testAdditionAndSubstractionAreInverse() { 247 | let today = moment() 248 | let soon = today + 1.hours 249 | let now = soon - 1.hours 250 | XCTAssertEqual(now, today, "Addition and subtraction are inverse operations") 251 | } 252 | 253 | func testFindMaximumMoment() { 254 | let today = moment() 255 | let format = "EE yyyy/dd--MMMM HH:mm ZZZZ" 256 | let birthday = moment("Tue 1973/4--September 12:30 GMT-03:00", dateFormat: format)! 257 | let ninetyFive = moment("1995-12-25")! 258 | let max = maximum(ninetyFive, today, birthday)! 259 | XCTAssertEqual(max, today, "Today is the maximum") 260 | } 261 | 262 | func testFindMinimumMoment() { 263 | let today = moment() 264 | let epoch = moment(0) 265 | let format = "EE yyyy/dd--MMMM HH:mm ZZZZ" 266 | let birthday = moment("Tue 1973/4--September 12:30 GMT-03:00", dateFormat: format)! 267 | let ninetyFive = moment("1995-12-25")! 268 | let min = minimum(today, epoch, ninetyFive, birthday)! 269 | XCTAssertEqual(min, epoch, "The minimum is the epoch") 270 | } 271 | 272 | func testMinimumWithoutParametersReturnsNil() { 273 | let min = minimum() 274 | XCTAssert(min == nil, "Without parameters, minimum() == nil") 275 | } 276 | 277 | func testMaximumWithoutParametersReturnsNil() { 278 | let max = maximum() 279 | XCTAssert(max == nil, "Without parameters, maximum() == nil") 280 | } 281 | 282 | func testCanGetParametersByGetter() { 283 | let today = moment() 284 | let seconds = today.get(.seconds) 285 | let minutes = today.get(.minutes) 286 | let hours = today.get(.hours) 287 | let days = today.get(.days) 288 | let months = today.get(.months) 289 | let weeks = today.get(.weeks) 290 | let years = today.get(.years) 291 | let quarters = today.get(.quarters) 292 | XCTAssertEqual(seconds, today.second, "Can use an enum to get properties") 293 | XCTAssertEqual(minutes, today.minute, "Can use an enum to get properties") 294 | XCTAssertEqual(hours, today.hour, "Can use an enum to get properties") 295 | XCTAssertEqual(days, today.day, "Can use an enum to get properties") 296 | XCTAssertEqual(months, today.month, "Can use an enum to get properties") 297 | XCTAssertEqual(weeks, today.weekOfYear, "Can use an enum to get properties") 298 | XCTAssertEqual(years, today.year, "Can use an enum to get properties") 299 | XCTAssertEqual(quarters, today.quarter, "Can use an enum to get properties") 300 | 301 | let second = today.get("s")! 302 | let minute = today.get("m")! 303 | let hour = today.get("H")! 304 | let day = today.get("d")! 305 | let month = today.get("M")! 306 | let week = today.get("w") 307 | let year = today.get("y") 308 | let quarter = today.get("Q") 309 | XCTAssertEqual(second, today.second, "Can use an enum to get properties") 310 | XCTAssertEqual(minute, today.minute, "Can use an enum to get properties") 311 | XCTAssertEqual(hour, today.hour, "Can use an enum to get properties") 312 | XCTAssertEqual(day, today.day, "Can use an enum to get properties") 313 | XCTAssertEqual(month, today.month, "Can use an enum to get properties") 314 | XCTAssertEqual(week, today.weekOfYear, "Can use an enum to get properties") 315 | XCTAssertEqual(year, today.year, "Can use an enum to get properties") 316 | XCTAssertEqual(quarter, today.quarter, "Can use an enum to get properties") 317 | } 318 | 319 | func testUsingWrongParameterNameYieldsNil() { 320 | let today = moment() 321 | let whatever = today.get("whatever") 322 | XCTAssert(whatever == nil, "There is no 'whatever' property to get") 323 | } 324 | 325 | func testFormatDates() { 326 | let timeZone = TimeZone(abbreviation: "GMT+01:00")! 327 | let birthday = moment("1973-09-04", timeZone: timeZone)! 328 | let str = birthday.format("EE QQQQ yyyy/dd/MMMM ZZZZ") 329 | XCTAssertEqual(str, "Tue 3rd quarter 1973/04/September GMT+01:00", "Complicated string") 330 | 331 | let standard = birthday.format() 332 | XCTAssertEqual(standard, "1973-09-04 00:00:00 GMT+01:00", "Standard output") 333 | } 334 | 335 | func testFormatDatesWithLocale() { 336 | let ad = Locale(identifier: "en_US_POSIX") 337 | let defaultFormatAd = moment("2015-09-04", locale: ad)! 338 | let giveFormatAd = moment("2015", dateFormat: "yyyy", locale: ad)! 339 | XCTAssertEqual(defaultFormatAd.year, 2015, "AD2015") 340 | XCTAssertEqual(giveFormatAd.year, 2015, "AD2015") 341 | 342 | let japanese = Locale(identifier: "ja_JP@calendar=japanese") 343 | let defaultFormatJapanese = moment("0027-09-04", locale: japanese)! 344 | let giveFormatJapanese = moment("0027", dateFormat: "yyyy", locale: japanese)! 345 | XCTAssertEqual(defaultFormatJapanese.year, 2015, "AD2015 == 27 Heisei period") 346 | XCTAssertEqual(giveFormatJapanese.year, 2015, "AD2015 == 27 Heisei period") 347 | } 348 | 349 | func testFutureMoment() { 350 | let duration = future() - moment() 351 | XCTAssertGreaterThan(duration.years, 1000, "The future is really far away") 352 | } 353 | 354 | func testPastMoment() { 355 | let duration = moment() - past() 356 | XCTAssertLessThan(1000, duration.years, "The past is really far away") 357 | } 358 | 359 | func testMomentWithTimeZone() { 360 | let zone = TimeZone(abbreviation: "PST")! 361 | let birthday = moment("1973-09-04", timeZone: zone)! 362 | let str = birthday.format("EE QQQQ yyyy/dd/MMMM HH:mm ZZZZ") 363 | XCTAssertEqual(str, "Tue 3rd quarter 1973/04/September 00:00 GMT-07:00", 364 | "A date in San Francisco") 365 | } 366 | 367 | func testTimeZoneChangesPreserveMomentInGMT() { 368 | // Feedback about #75 369 | let timeZone = TimeZone(secondsFromGMT: -10800)! 370 | let locale = Locale(identifier: "en_US_POSIX") 371 | let dateString = "2016-10-12T10:02:50" 372 | let dateFormat = "yyy-MM-dd'T'HH:mm:ss" 373 | let birthday = moment(dateString, dateFormat: dateFormat, timeZone: timeZone, locale: locale)! 374 | let formatted = birthday.format(dateFormat) 375 | XCTAssertEqual(formatted, dateString) 376 | XCTAssertEqual(birthday.hour, 10) 377 | XCTAssertEqual(birthday.minute, 2) 378 | 379 | let displayZone = TimeZone(abbreviation: "PST")! 380 | let str = birthday.format("EE QQQQ yyyy/dd/MMMM HH:mm ZZZZ", displayZone) 381 | XCTAssertEqual(str, "Wed 4th quarter 2016/12/October 06:02 GMT-07:00", 382 | "A date in San Francisco") 383 | 384 | } 385 | 386 | func testTransformTimeZone() { 387 | // Fixes #75 388 | let timeZone = TimeZone(secondsFromGMT: -10800)! 389 | let locale = Locale(identifier: "en_US_POSIX") 390 | let dateString = "2016-10-12T10:02:50" 391 | let dateFormat = "yyy-MM-dd'T'HH:mm:ss" 392 | let birthday = moment(dateString, dateFormat: dateFormat, timeZone: timeZone, locale: locale)! 393 | let formatted = birthday.format(dateFormat) 394 | XCTAssertEqual(formatted, dateString) 395 | XCTAssertEqual(birthday.hour, 10) 396 | XCTAssertEqual(birthday.minute, 2) 397 | 398 | let displayZone = TimeZone(abbreviation: "PST")! 399 | let birthdayInSF = moment(birthday, timeZone: displayZone) 400 | XCTAssertEqual(birthdayInSF.hour, 6) 401 | XCTAssertEqual(birthdayInSF.minute, 2) 402 | } 403 | 404 | func testUTCMomentSupport() { 405 | let greenwich = utc() 406 | let str = greenwich.format("ZZZZ") 407 | XCTAssertEqual(str, "GMT", "The timezone is UTC") 408 | } 409 | 410 | func testFormatWithTimeZone() { 411 | let momentZone = TimeZone(abbreviation: "PST")! 412 | let birthday = moment("1973-09-04", timeZone: momentZone)! 413 | let displayZone = TimeZone(abbreviation: "CET")! 414 | let str = birthday.format("EE QQQQ yyyy/dd/MMMM HH:mm ZZZZ", displayZone) 415 | XCTAssertEqual(str, "Tue 3rd quarter 1973/04/September 08:00 GMT+01:00", 416 | "A date in San Francisco") 417 | } 418 | 419 | func testLocaleSupport() { 420 | let français = Locale(identifier: "fr_FR") 421 | let anniversaire = moment("1973-09-04", locale: français)! 422 | let jour = anniversaire.weekdayName 423 | let mois = anniversaire.monthName 424 | XCTAssertEqual(jour, "mardi", "Eh ben bravo!") 425 | XCTAssertEqual(mois, "septembre", "Eh ben bravo!") 426 | 427 | let deutsch = Locale(identifier: "de_DE") 428 | let geburtstag = moment("1973-03-04", locale: deutsch)! 429 | let tag = geburtstag.weekdayName 430 | let monat = geburtstag.monthName 431 | XCTAssertEqual(tag, "Sonntag", "Ach so!") 432 | XCTAssertEqual(monat, "März", "Ach so!") 433 | } 434 | 435 | func testStartOfYear() { 436 | let obj = moment([2015, 10, 19, 20, 45, 34])!.startOf("y") 437 | XCTAssertEqual(obj.year, 2015, "The year should match") 438 | XCTAssertEqual(obj.month, 1, "The month should match") 439 | XCTAssertEqual(obj.day, 1, "The day should match") 440 | XCTAssertEqual(obj.hour, 0, "The hour should match") 441 | XCTAssertEqual(obj.minute, 0, "The minute should match") 442 | XCTAssertEqual(obj.second, 0, "The second should match") 443 | } 444 | 445 | func testStartOfMonth() { 446 | let obj = moment([2015, 10, 19, 20, 45, 34])!.startOf("M") 447 | XCTAssertEqual(obj.year, 2015, "The year should match") 448 | XCTAssertEqual(obj.month, 10, "The month should match") 449 | XCTAssertEqual(obj.day, 1, "The day should match") 450 | XCTAssertEqual(obj.hour, 0, "The hour should match") 451 | XCTAssertEqual(obj.minute, 0, "The minute should match") 452 | XCTAssertEqual(obj.second, 0, "The second should match") 453 | } 454 | 455 | func testStartOfWeek() { 456 | // test for year change in EU timezone (first day of week: monday) 457 | let w0 = moment([2016, 01, 02, 20, 45, 34], timeZone: TimeZone(identifier: "Europe/Paris")!, locale: Locale(identifier: "fr_FR"))! 458 | .startOf(.weeks) 459 | XCTAssertEqual(w0.year, 2015, "The year should match") 460 | XCTAssertEqual(w0.month, 12, "The month should match") 461 | XCTAssertEqual(w0.day, 28, "The day should match") 462 | XCTAssertEqual(w0.hour, 0, "The hour should match") 463 | XCTAssertEqual(w0.minute, 0, "The minute should match") 464 | XCTAssertEqual(w0.second, 0, "The second should match") 465 | 466 | // test for year change in US timezone (first day of week: sunday) 467 | let w1 = moment([2016, 01, 02, 20, 45, 34], timeZone: TimeZone(identifier: "US/Eastern")!, locale: Locale(identifier: "en_US"))! 468 | .startOf(.weeks) 469 | XCTAssertEqual(w1.year, 2015, "The year should match") 470 | XCTAssertEqual(w1.month, 12, "The month should match") 471 | XCTAssertEqual(w1.day, 27, "The day should match") 472 | XCTAssertEqual(w1.hour, 0, "The hour should match") 473 | XCTAssertEqual(w1.minute, 0, "The minute should match") 474 | XCTAssertEqual(w1.second, 0, "The second should match") 475 | 476 | // test for region with first day of week = monday 477 | let w2 = moment([2017, 05, 21, 00, 00], timeZone: TimeZone(identifier: "Europe/Paris")!, locale: Locale(identifier: "fr_FR"))! 478 | .startOf(.weeks) 479 | XCTAssertEqual(w2.year, 2017, "The year should match") 480 | XCTAssertEqual(w2.month, 05, "The month should match") 481 | XCTAssertEqual(w2.day, 15, "The day should match") 482 | XCTAssertEqual(w2.hour, 0, "The hour should match") 483 | XCTAssertEqual(w2.minute, 0, "The minute should match") 484 | XCTAssertEqual(w2.second, 0, "The second should match") 485 | 486 | // tests for region with first day of week = monday 487 | let w3 = moment([2017, 05, 20, 00, 00], timeZone: TimeZone(identifier: "US/Eastern")!, locale: Locale(identifier: "en_US"))! 488 | .startOf(.weeks) 489 | XCTAssertEqual(w3.year, 2017, "The year should match") 490 | XCTAssertEqual(w3.month, 05, "The month should match") 491 | XCTAssertEqual(w3.day, 14, "The day should match") 492 | XCTAssertEqual(w3.hour, 0, "The hour should match") 493 | XCTAssertEqual(w3.minute, 0, "The minute should match") 494 | XCTAssertEqual(w3.second, 0, "The second should match") 495 | 496 | let w4 = moment([2017, 05, 21, 00, 00], timeZone: TimeZone(identifier: "US/Eastern")!, locale: Locale(identifier: "en_US"))! 497 | .startOf(.weeks) 498 | XCTAssertEqual(w4.year, 2017, "The year should match") 499 | XCTAssertEqual(w4.month, 05, "The month should match") 500 | XCTAssertEqual(w4.day, 21, "The day should match") 501 | XCTAssertEqual(w4.hour, 0, "The hour should match") 502 | XCTAssertEqual(w4.minute, 0, "The minute should match") 503 | XCTAssertEqual(w4.second, 0, "The second should match") 504 | } 505 | 506 | func testStartOfDay() { 507 | let obj = moment([2015, 10, 19, 20, 45, 34])!.startOf(.days) 508 | XCTAssertEqual(obj.year, 2015, "The year should match") 509 | XCTAssertEqual(obj.month, 10, "The month should match") 510 | XCTAssertEqual(obj.day, 19, "The day should match") 511 | XCTAssertEqual(obj.hour, 0, "The hour should match") 512 | XCTAssertEqual(obj.minute, 0, "The minute should match") 513 | XCTAssertEqual(obj.second, 0, "The second should match") 514 | } 515 | 516 | func testStartOfHour() { 517 | let obj = moment([2015, 10, 19, 20, 45, 34])!.startOf(.hours) 518 | XCTAssertEqual(obj.year, 2015, "The year should match") 519 | XCTAssertEqual(obj.month, 10, "The month should match") 520 | XCTAssertEqual(obj.day, 19, "The day should match") 521 | XCTAssertEqual(obj.hour, 20, "The hour should match") 522 | XCTAssertEqual(obj.minute, 0, "The minute should match") 523 | XCTAssertEqual(obj.second, 0, "The second should match") 524 | } 525 | 526 | func testStartOfMinute() { 527 | let obj = moment([2015, 10, 19, 20, 45, 34])!.startOf(.minutes) 528 | XCTAssertEqual(obj.year, 2015, "The year should match") 529 | XCTAssertEqual(obj.month, 10, "The month should match") 530 | XCTAssertEqual(obj.day, 19, "The day should match") 531 | XCTAssertEqual(obj.hour, 20, "The day should match") 532 | XCTAssertEqual(obj.minute, 45, "The minute should match") 533 | XCTAssertEqual(obj.second, 0, "The second should match") 534 | } 535 | 536 | func testStartOfSecond() { 537 | let obj = moment([2015, 10, 19, 20, 45, 34])!.startOf(.seconds) 538 | XCTAssertEqual(obj.year, 2015, "The year should match") 539 | XCTAssertEqual(obj.month, 10, "The month should match") 540 | XCTAssertEqual(obj.day, 19, "The day should match") 541 | XCTAssertEqual(obj.hour, 20, "The day should match") 542 | XCTAssertEqual(obj.minute, 45, "The minute should match") 543 | XCTAssertEqual(obj.second, 34, "The second should match") 544 | } 545 | 546 | func testEndOfYear() { 547 | let obj = moment([2015, 10, 19, 20, 45, 34])!.endOf(.years) 548 | XCTAssertEqual(obj.year, 2015, "The year should match") 549 | XCTAssertEqual(obj.month, 12, "The month should match") 550 | XCTAssertEqual(obj.day, 31, "The day should match") 551 | XCTAssertEqual(obj.hour, 23, "The hour should match") 552 | XCTAssertEqual(obj.minute, 59, "The minute should match") 553 | XCTAssertEqual(obj.second, 59, "The second should match") 554 | } 555 | 556 | func testEndOfMonth() { 557 | let obj = moment([2015, 01, 19, 20, 45, 34])!.endOf(.months) 558 | XCTAssertEqual(obj.year, 2015, "The year should match") 559 | XCTAssertEqual(obj.month, 01, "The month should match") 560 | XCTAssertEqual(obj.day, 30, "The day should match") 561 | XCTAssertEqual(obj.hour, 23, "The hour should match") 562 | XCTAssertEqual(obj.minute, 59, "The minute should match") 563 | XCTAssertEqual(obj.second, 59, "The second should match") 564 | } 565 | 566 | func testEndOfWeek() { 567 | // test for year change in EU timezone (first day of week: monday) 568 | let w0 = moment([2015, 12, 29, 20, 45, 34], timeZone: TimeZone(identifier: "Europe/Paris")!, locale: Locale(identifier: "fr_FR"))! 569 | .endOf(.weeks) 570 | XCTAssertEqual(w0.year, 2016, "The year should match") 571 | XCTAssertEqual(w0.month, 01, "The month should match") 572 | XCTAssertEqual(w0.day, 03, "The day should match") 573 | XCTAssertEqual(w0.hour, 23, "The hour should match") 574 | XCTAssertEqual(w0.minute, 59, "The minute should match") 575 | XCTAssertEqual(w0.second, 59, "The second should match") 576 | 577 | // test for year change in US timezone (first day of week: sunday) 578 | let w1 = moment([2015, 12, 29, 20, 45, 34], timeZone: TimeZone(identifier: "US/Eastern")!, locale: Locale(identifier: "en_US"))! 579 | .endOf(.weeks) 580 | XCTAssertEqual(w1.year, 2016, "The year should match") 581 | XCTAssertEqual(w1.month, 01, "The month should match") 582 | XCTAssertEqual(w1.day, 02, "The day should match") 583 | XCTAssertEqual(w1.hour, 23, "The hour should match") 584 | XCTAssertEqual(w1.minute, 59, "The minute should match") 585 | XCTAssertEqual(w1.second, 59, "The second should match") 586 | 587 | // test for region with first day of week = monday 588 | let w2 = moment([2017, 05, 21, 00, 00], timeZone: TimeZone(identifier: "Europe/Paris")!, locale: Locale(identifier: "fr_FR"))! 589 | .endOf(.weeks) 590 | XCTAssertEqual(w2.year, 2017, "The year should match") 591 | XCTAssertEqual(w2.month, 05, "The month should match") 592 | XCTAssertEqual(w2.day, 21, "The day should match") 593 | XCTAssertEqual(w2.hour, 23, "The hour should match") 594 | XCTAssertEqual(w2.minute, 59, "The minute should match") 595 | XCTAssertEqual(w2.second, 59, "The second should match") 596 | 597 | // tests for region with first day of week = monday 598 | let w3 = moment([2017, 05, 21, 00, 00], timeZone: TimeZone(identifier: "US/Eastern")!, locale: Locale(identifier: "en_US"))! 599 | .endOf(.weeks) 600 | XCTAssertEqual(w3.year, 2017, "The year should match") 601 | XCTAssertEqual(w3.month, 05, "The month should match") 602 | XCTAssertEqual(w3.day, 27, "The day should match") 603 | XCTAssertEqual(w3.hour, 23, "The hour should match") 604 | XCTAssertEqual(w3.minute, 59, "The minute should match") 605 | XCTAssertEqual(w3.second, 59, "The second should match") 606 | 607 | let w4 = moment([2017, 05, 20, 00, 00], timeZone: TimeZone(identifier: "US/Eastern")!, locale: Locale(identifier: "en_US"))! 608 | .endOf(.weeks) 609 | XCTAssertEqual(w4.year, 2017, "The year should match") 610 | XCTAssertEqual(w4.month, 05, "The month should match") 611 | XCTAssertEqual(w4.day, 20, "The day should match") 612 | XCTAssertEqual(w4.hour, 23, "The hour should match") 613 | XCTAssertEqual(w4.minute, 59, "The minute should match") 614 | XCTAssertEqual(w4.second, 59, "The second should match") 615 | } 616 | 617 | func testEndOfDay() { 618 | let obj = moment([2015, 10, 19, 20, 45, 34])!.endOf("d") 619 | XCTAssertEqual(obj.year, 2015, "The year should match") 620 | XCTAssertEqual(obj.month, 10, "The month should match") 621 | XCTAssertEqual(obj.day, 19, "The day should match") 622 | XCTAssertEqual(obj.hour, 23, "The day should match") 623 | XCTAssertEqual(obj.minute, 59, "The minute should match") 624 | XCTAssertEqual(obj.second, 59, "The second should match") 625 | } 626 | 627 | func testEpoch() { 628 | let gmt = moment("2015-05-29T01:40:17", timeZone: TimeZone(identifier: "GMT")!)! 629 | let jst = moment("2015-05-29T10:40:17", timeZone: TimeZone(identifier: "Asia/Tokyo")!)! 630 | XCTAssertEqual(moment(0.0).epoch(), 0.0, "The zero epoch should match") 631 | XCTAssertEqual(moment(1432863617.0).epoch(), 1432863617.0, 632 | "The non zero epoch should match") 633 | XCTAssertEqual(jst.epoch(), gmt.epoch(), "The JST epoch should match GMT epoch") 634 | } 635 | 636 | func testPublicDate() { 637 | let date = Date() 638 | let now = moment(date) 639 | XCTAssertEqual(now.date, date, "The moment's date should be publicly readable") 640 | let expectedString = ["The moment's timeZone should be publicly readable", 641 | "and default to the current timezone"].joined(separator: " ") 642 | XCTAssertEqual(now.timeZone, TimeZone.current, expectedString) 643 | } 644 | 645 | func testPublicTimeZone() { 646 | let date = Date() 647 | let now = moment(date) 648 | let expectedString = ["The moment's timeZone should be publicly readable", 649 | "and default to the current timezone"].joined(separator: " ") 650 | XCTAssertEqual(now.timeZone, TimeZone.current, expectedString) 651 | } 652 | 653 | func testPublicLocale() { 654 | let date = Date() 655 | let now = moment(date) 656 | let expectedString = ["The moment's locale should be publicly readable", 657 | "and default to the current locale"].joined(separator: " ") 658 | 659 | // Using autoupdatingCurrent here, because 660 | // https://github.com/lionheart/openradar-mirror/issues/15493 661 | XCTAssertEqual(now.locale, Locale.autoupdatingCurrent, expectedString) 662 | } 663 | 664 | func testAddingInt() { 665 | // This is to verify that issue #48 is corrected 666 | // https://github.com/akosma/SwiftMoment/issues/48 667 | let problem = moment("2016-07-01")! 668 | let result = problem.add(1, .months) 669 | let expected = moment("2016-07-31")! 670 | XCTAssertEqual(result, expected) 671 | } 672 | 673 | func testAddSmallTimeSpans() { 674 | let now1 = moment() 675 | let now2 = now1.add(1, .seconds) 676 | let now3 = now2.add(1, .minutes) 677 | let now4 = now3.add(1, .hours) 678 | 679 | let another1 = moment(now1) 680 | let another2 = another1.add(1, "s") 681 | let another3 = another2.add(1, "m") 682 | let another4 = another3.add(1, "H") 683 | 684 | XCTAssertEqual(now4, another4) 685 | } 686 | 687 | func testSubstractSmallTimeSpans() { 688 | let now1 = moment() 689 | let now2 = now1.subtract(1, .seconds) 690 | let now3 = now2.subtract(1, .minutes) 691 | let now4 = now3.subtract(1, .hours) 692 | 693 | let another1 = moment(now1) 694 | let another2 = another1.subtract(1, "s") 695 | let another3 = another2.subtract(1, "m") 696 | let another4 = another3.subtract(1, "H") 697 | 698 | XCTAssertEqual(now4, another4) 699 | } 700 | 701 | func testTimeZoneChangeAdd() { 702 | let now = utc() 703 | let tomorrow = now.add(1, .days) 704 | XCTAssertEqual(now.timeZone, tomorrow.timeZone) 705 | } 706 | 707 | func testTimeZoneChangeSubtract() { 708 | let now = utc() 709 | let yesterday = now.subtract(1, .quarters) 710 | XCTAssertEqual(now.timeZone, yesterday.timeZone) 711 | } 712 | 713 | func testTimeZoneChangeStartOf() { 714 | let now = utc() 715 | let startOfDay = now.startOf(.days) 716 | XCTAssertEqual(now.timeZone, startOfDay.timeZone) 717 | } 718 | 719 | func testTimeZoneChangeEndOf() { 720 | let now = utc() 721 | let endOfDay = now.endOf(.days) 722 | XCTAssertEqual(now.timeZone, endOfDay.timeZone) 723 | } 724 | 725 | func testTimeZoneStartOfDay() { 726 | let cet = TimeZone(abbreviation: "CET")! 727 | let edt = TimeZone(abbreviation: "EDT")! 728 | let nowCet = moment(cet) 729 | let nowEdt = moment(edt) 730 | let startOfDayCet = nowCet.startOf(.days) 731 | let startOfDayEdt = nowEdt.startOf(.days) 732 | XCTAssertEqual(startOfDayCet.hour, 0) 733 | XCTAssertEqual(startOfDayEdt.hour, 0) 734 | } 735 | 736 | func testWrongFormatParametersReturnNil() { 737 | let mom = moment("sdfg32-435-fdg34-2345", dateFormat: "324265;KJ235-56") 738 | XCTAssertNil(mom) 739 | } 740 | 741 | func testWrongArrayReturnsNil() { 742 | let arr = [Int]() 743 | let mom1 = moment(arr) 744 | XCTAssertNil(mom1) 745 | 746 | let mom2 = moment([]) 747 | XCTAssertNil(mom2) 748 | 749 | let dict = [String: Int]() 750 | let mom3 = moment(dict) 751 | XCTAssertNil(mom3) 752 | 753 | let mom4 = moment(["savarasasa": 234656]) 754 | XCTAssertNil(mom4) 755 | } 756 | 757 | func testWrongUnitInAddReturnsSelf() { 758 | let now = moment() 759 | let another = now.add(1, "whatever") 760 | XCTAssertEqual(another, now) 761 | } 762 | 763 | func testWrongUnitInSubstractReturnsSelf() { 764 | let now = moment() 765 | let another = now.subtract(1, "whatever") 766 | XCTAssertEqual(another, now) 767 | } 768 | 769 | func testWrongUnitInStartOfReturnsSelf() { 770 | let now = moment() 771 | let another = now.startOf("whatever") 772 | XCTAssertEqual(another, now) 773 | } 774 | 775 | func testWrongUnitInEndOfReturnsSelf() { 776 | let now = moment() 777 | let another = now.endOf("whatever") 778 | XCTAssertEqual(another, now) 779 | } 780 | 781 | func testDescriptions() { 782 | let now = moment() 783 | let str1 = now.description 784 | let str2 = now.debugDescription 785 | XCTAssertEqual(now.format(), str1) 786 | XCTAssertEqual(now.format(), str2) 787 | } 788 | 789 | } 790 | --------------------------------------------------------------------------------